v0.3.14-pre.007

This commit is contained in:
2026-09-12 07:47:16 +02:00
parent ae712eae64
commit 887664f3c0
9 changed files with 619 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
// version: 4
// version: 5
fn network() -> std::option::Option<ksp_store_lib::RawNetworkId> {
return match ksp_store_lib::RawNetworkId::new("mainnet") {
@@ -453,3 +453,23 @@ fn pre_005_coverage_epoch_ledger_is_bounded_monotone_and_capability_bound() {
assert!(overflow.validate_invariants(std::slice::from_ref(&matching)).is_err());
return;
}
#[test]
fn pre_007_known_reference_obligation_preserves_exact_reference_slot_and_commitment() {
let network = match network() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let reference = ksp_store_lib::RawTransactionReference::new(network, ksp_store_lib::RawTransactionSignature::new([9_u8; 64]));
let obligation =
match crate::RawTransactionIngestKnownReferenceObligation::new(reference.clone(), 4242, ksp_onchain_transport_lib::SolanaCommitment::Confirmed) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("unexpected known-reference obligation failure: {error}"),
};
assert_eq!(obligation.reference(), &reference);
assert_eq!(obligation.slot(), 4242);
assert_eq!(obligation.commitment(), ksp_onchain_transport_lib::SolanaCommitment::Confirmed);
let processed = crate::RawTransactionIngestKnownReferenceObligation::new(reference, 4242, ksp_onchain_transport_lib::SolanaCommitment::Processed);
assert!(processed.is_err());
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
// version: 26
// version: 27
fn grpc_endpoint(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider");
@@ -450,6 +450,16 @@ const PRE_004_ZERO_SIGNATURE_TEXT: &str = "1111111111111111111111111111111111111
const PRE_004_ZERO_TRANSACTION_BASE64: &str = "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
fn http_pool_for_url(url: &str, cluster: &str, endpoint_name: &str, provider: &str) -> std::option::Option<ksp_onchain_transport_lib::HttpTransportPool> {
return http_pool_for_url_with_request_kinds(url, cluster, endpoint_name, provider, &["get_transaction"]);
}
fn http_pool_for_url_with_request_kinds(
url: &str,
cluster: &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(url) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
@@ -457,7 +467,7 @@ fn http_pool_for_url(url: &str, cluster: &str, endpoint_name: &str, provider: &s
let role = ksp_onchain_transport_lib::HttpEndpointRoleSettings::new(
ksp_onchain_transport_lib::HttpRoleName::new("hydration"),
true,
std::vec![ksp_onchain_transport_lib::HttpRequestKind::new("get_transaction")],
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,
@@ -517,6 +527,29 @@ fn signal_source_for_http_url_with_commitment(
};
}
fn signal_source_for_http_url_with_request_kinds(url: &str, request_kinds: &[&str]) -> std::option::Option<crate::RawTransactionIngestYellowstoneSource> {
let endpoint = match grpc_endpoint("devnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
let channel = match ksp_onchain_transport_lib::YellowstoneGrpcChannel::prepare(&endpoint) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let request = match transaction_request(std::option::Option::Some(ksp_onchain_transport_lib::SolanaCommitment::Confirmed)) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
let pool = match http_pool_for_url_with_request_kinds(url, "devnet", "http-hydration-fixture", "fixture-http-provider", request_kinds) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
return match crate::RawTransactionIngestYellowstoneSource::new(channel, request, pool, ksp_onchain_transport_lib::HttpRoleName::new("hydration")) {
std::result::Result::Ok(value) => std::option::Option::Some(value),
std::result::Result::Err(_) => std::option::Option::None,
};
}
fn standard_logs_source_for_http_url(
url: &str,
filter: ksp_onchain_transport_lib::SolanaLogsSubscribeFilter,
@@ -3140,6 +3173,196 @@ fn v0_3_14_pre_006_with_limit_discovery_never_uses_tip_alone_as_tail_coverage_pr
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_14_pre_007_known_reference_hydration_reuses_global_registry_and_available_material() {
let body = std::format!(
"{{\"jsonrpc\":\"2.0\",\"result\":{{\"slot\":42,\"blockTime\":1760000120,\"transaction\":[\"{}\",\"base64\"],\"meta\":null,\"version\":0,\"transactionIndex\":7}},\"id\":1}}",
PRE_004_ZERO_TRANSACTION_BASE64,
);
let (url, server) = match serve_http_once(body) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let source = match signal_source_for_http_url(url.as_str()) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let settings = match pre_004_settings() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let signal = match pre_004_signal(&source, super::RawTransactionIngestSourceFamily::Transaction, 42, 7, &["tx-fixture"], 0) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let hydration = source.hydration_context();
let key = match super::hydration_key(&hydration, &signal) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = std::sync::Arc::new(super::RawTransactionIngestGlobalHydrationRegistry::new(4, 1));
let first = super::fetch_hydration_shared(
std::sync::Arc::clone(&registry),
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key.clone(),
hydration.commitment,
);
let second = super::fetch_hydration_shared(
std::sync::Arc::clone(&registry),
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key,
hydration.commitment,
);
let (first, second) = tokio::join!(first, second);
let first = match first {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert!(second.is_ok());
let request = match server.join() {
std::result::Result::Ok(std::result::Result::Ok(value)) => value,
_ => return,
};
assert!(request.contains("\"method\":\"getTransaction\""));
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_760_000_200_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let resolved = super::resolve_known_reference_hydration(&hydration, &settings, signal, received_at, &first.observed);
let ingress = match resolved {
std::result::Result::Ok(super::RawTransactionIngestKnownReferenceHydrationResolution::Available(value)) => value,
_ => return,
};
let (mut admission, sender) = crate::RawTransactionAdmission::new(1);
if sender.send(ingress).await.is_err() {
return;
}
std::mem::drop(sender);
let acquisition = match admission.receive(settings.network()).await {
std::result::Result::Ok(std::option::Option::Some(value)) => value,
_ => return,
};
assert_eq!(acquisition.transaction().slot(), 42);
assert_eq!(acquisition.transaction().reference().signature().as_bytes(), &[0_u8; 64]);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_14_pre_007_missing_known_reference_remains_open_without_block_capability() {
let (url, server) = match serve_http_once("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}".to_owned()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let source = match signal_source_for_http_url(url.as_str()) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let settings = match pre_004_settings() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let signal = match pre_004_signal(&source, super::RawTransactionIngestSourceFamily::TransactionStatus, 77, 0, &["status-fixture"], 0) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let hydration = source.hydration_context();
let key = match super::hydration_key(&hydration, &signal) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = std::sync::Arc::new(super::RawTransactionIngestGlobalHydrationRegistry::new(2, 1));
let fetched = super::fetch_hydration_shared(
registry,
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key,
hydration.commitment,
)
.await;
let fetched = match fetched {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let _request = match server.join() {
std::result::Result::Ok(std::result::Result::Ok(value)) => value,
_ => return,
};
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_760_000_200_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let resolved = super::resolve_known_reference_hydration(&hydration, &settings, signal, received_at, &fetched.observed);
let (disposition, obligation) = match resolved {
std::result::Result::Ok(super::RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation }) => (disposition, obligation),
_ => return,
};
assert_eq!(disposition, super::RawTransactionIngestKnownReferenceMissingDisposition::AwaitCoverage);
assert_eq!(obligation.slot(), 77);
assert_eq!(obligation.commitment(), ksp_onchain_transport_lib::SolanaCommitment::Confirmed);
assert_eq!(obligation.reference().signature().as_bytes(), &[0_u8; 64]);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_14_pre_007_missing_known_reference_prefers_same_role_block_slot_when_supported() {
let (url, server) = match serve_http_once("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}".to_owned()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let source = match signal_source_for_http_url_with_request_kinds(url.as_str(), &["get_transaction", "get_block"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let settings = match pre_004_settings() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let signal = match pre_004_signal(&source, super::RawTransactionIngestSourceFamily::Transaction, 88, 0, &["tx-fixture"], 0) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let hydration = source.hydration_context();
let key = match super::hydration_key(&hydration, &signal) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = std::sync::Arc::new(super::RawTransactionIngestGlobalHydrationRegistry::new(2, 1));
let fetched = super::fetch_hydration_shared(
registry,
hydration.http_pool.clone(),
hydration.hydration_role.clone(),
hydration.network.clone(),
key,
hydration.commitment,
)
.await;
let fetched = match fetched {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let _request = match server.join() {
std::result::Result::Ok(std::result::Result::Ok(value)) => value,
_ => return,
};
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_760_000_200_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let resolved = super::resolve_known_reference_hydration(&hydration, &settings, signal, received_at, &fetched.observed);
let (disposition, obligation) = match resolved {
std::result::Result::Ok(super::RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation }) => (disposition, obligation),
_ => return,
};
assert_eq!(disposition, super::RawTransactionIngestKnownReferenceMissingDisposition::PreferBlockSlot);
assert_eq!(obligation.slot(), 88);
return;
}
#[test]
fn v0_3_13_pre_006_http_block_polling_qualifies_legacy_v0_v1_and_rejects_ambiguous_or_future_versions() {
let cases = [