v0.3.13-pre.009

This commit is contained in:
2026-09-10 19:56:16 +02:00
parent 1746d47412
commit 665d7d2bb6
15 changed files with 1051 additions and 45 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/admission.rs
// version: 5
// version: 6
fn material(
network: &str,
@@ -311,3 +311,104 @@ async fn v0_3_13_pre_008_distinct_source_keys_produce_distinct_idempotent_observ
assert_ne!(first.observation().observation_key(), second.observation().observation_key());
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_13_pre_009_duplicate_storm_cannot_starve_second_ready_source_on_bounded_admission() {
let (network, initial_material) = match material("mainnet", 60, "AQID") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let (_, peer_material) = match material("mainnet", 99, "BwgJ") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let initial_provenance = match provenance() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let storm_provenance = match provenance() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let peer_provenance = match provenance() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let (mut admission, sender) = crate::RawTransactionAdmission::new(1);
assert!(
sender
.send(crate::RawTransactionIngress {
material: initial_material,
network: network.clone(),
provenance: initial_provenance,
source_key: [60_u8; 32],
})
.await
.is_ok()
);
let storm_sender = sender.clone();
let storm_network = network.clone();
let storm_task = tokio::spawn(async move {
for _ in 0..8 {
let material = ksp_raw_transaction_lib::RawTransactionMaterial::binary_base64(
storm_network.clone(),
ksp_store_lib::RawTransactionSignature::new([61_u8; 64]),
42,
std::option::Option::Some(1_700_000_000),
"BAUG",
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
);
if storm_sender
.send(crate::RawTransactionIngress {
material,
network: storm_network.clone(),
provenance: storm_provenance.clone(),
source_key: [61_u8; 32],
})
.await
.is_err()
{
return false;
}
}
return true;
});
tokio::task::yield_now().await;
let peer_sender = sender.clone();
let peer_network = network.clone();
let peer_task = tokio::spawn(async move {
return peer_sender
.send(crate::RawTransactionIngress { material: peer_material, network: peer_network, provenance: peer_provenance, source_key: [99_u8; 32] })
.await
.is_ok();
});
tokio::task::yield_now().await;
assert_eq!(admission.queue_depth(), 1);
let first = match admission.receive(&network).await {
std::result::Result::Ok(std::option::Option::Some(value)) => value,
_ => return,
};
assert_eq!(first.transaction().reference().signature().as_bytes(), &[60_u8; 64]);
let second = match admission.receive(&network).await {
std::result::Result::Ok(std::option::Option::Some(value)) => value,
_ => return,
};
assert_eq!(second.transaction().reference().signature().as_bytes(), &[61_u8; 64]);
let third = match admission.receive(&network).await {
std::result::Result::Ok(std::option::Option::Some(value)) => value,
_ => return,
};
assert_eq!(third.transaction().reference().signature().as_bytes(), &[99_u8; 64]);
for _ in 0..7 {
let next = admission.receive(&network).await;
assert!(matches!(next, std::result::Result::Ok(std::option::Option::Some(_))));
assert!(admission.queue_depth() <= 1);
}
let peer_joined = peer_task.await;
assert!(matches!(peer_joined, std::result::Result::Ok(true)));
let storm_joined = storm_task.await;
assert!(matches!(storm_joined, std::result::Result::Ok(true)));
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/persistence.rs
// version: 2
// version: 3
#[derive(Clone, Copy)]
enum PortResponse {
@@ -92,6 +92,17 @@ fn acquisition_with_observation_key(
network_name: &str,
signature_byte: u8,
observation_byte: u8,
) -> std::option::Option<ksp_raw_transaction_lib::RawTransactionAcquisition> {
return acquisition_with_shape(network_name, signature_byte, observation_byte, 42, std::option::Option::Some(1_700_000_000), "AQID");
}
fn acquisition_with_shape(
network_name: &str,
signature_byte: u8,
observation_byte: u8,
slot: u64,
block_time: std::option::Option<i64>,
transaction_data: &str,
) -> std::option::Option<ksp_raw_transaction_lib::RawTransactionAcquisition> {
let network = match ksp_store_lib::RawNetworkId::new(network_name) {
std::result::Result::Ok(value) => value,
@@ -101,9 +112,9 @@ fn acquisition_with_observation_key(
let material = ksp_raw_transaction_lib::RawTransactionMaterial::binary_base64(
network,
signature,
42,
std::option::Option::Some(1_700_000_000),
"AQID",
slot,
block_time,
transaction_data,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
@@ -357,3 +368,41 @@ async fn v0_3_13_pre_008_replayed_same_observation_is_idempotent_without_raw_res
assert_eq!(second_outcome.observation(), crate::RawTransactionIngestObservationPersistence::AlreadyPresent);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_13_pre_009_source_skew_and_provider_disagreement_fail_before_additional_observation() {
let cases = [
(43_u64, std::option::Option::Some(1_700_000_000_i64), "AQID"),
(42_u64, std::option::Option::Some(1_700_000_001_i64), "AQID"),
(42_u64, std::option::Option::Some(1_700_000_000_i64), "BAUG"),
];
for (index, (slot, block_time, transaction_data)) in cases.into_iter().enumerate() {
let network = match network("mainnet") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let port = FakePersistencePort::new(
network,
PortResponse::Outcome(ksp_store_lib::RawEntityWriteOutcome::Inserted, ksp_store_lib::RawObservationWriteOutcome::Inserted),
);
let convergence = crate::RawTransactionIngestPersistenceConvergence::new(8);
let first = match acquisition_with_shape("mainnet", 51, 10, 42, std::option::Option::Some(1_700_000_000), "AQID") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let divergent = match acquisition_with_shape("mainnet", 51, index as u8 + 20, slot, block_time, transaction_data) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
assert!(crate::persist_raw_transaction_ingest_converged_acquisition(&port, first, &convergence).await.is_ok());
let conflict = crate::persist_raw_transaction_ingest_converged_acquisition(&port, divergent, &convergence).await;
let error = match conflict {
std::result::Result::Ok(_) => return,
std::result::Result::Err(value) => value,
};
assert_eq!(error.code(), crate::ERROR_CODE_RAW_TRANSACTION_INGEST_CONTENT_CONFLICT);
assert_eq!(port.calls.load(std::sync::atomic::Ordering::Acquire), 1);
assert_eq!(port.observation_calls.load(std::sync::atomic::Ordering::Acquire), 0);
}
return;
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
// version: 20
// version: 21
fn grpc_endpoint(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider");
@@ -3008,7 +3008,7 @@ fn v0_3_13_pre_008_global_hydration_registry_coalesces_cross_source_key_to_one_l
network,
signature: ksp_store_lib::RawTransactionSignature::new([61_u8; 64]),
};
let registry = super::RawTransactionIngestGlobalHydrationRegistry::new(&settings);
let registry = super::RawTransactionIngestGlobalHydrationRegistry::new(settings.admission_queue_capacity(), settings.persistence_concurrency());
let (first_leader, _first_receiver) = match registry.subscribe_or_lead(&key) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
@@ -3034,3 +3034,107 @@ fn v0_3_13_pre_008_global_hydration_registry_coalesces_cross_source_key_to_one_l
assert!(third_leader);
return;
}
#[test]
fn v0_3_13_pre_009_hydration_quotas_partition_exact_bounds_and_reject_underprovision() {
assert!(super::validate_hydration_fairness_capacity(8, 5, 3).is_ok());
let pending_error = match super::validate_hydration_fairness_capacity(2, 5, 3) {
std::result::Result::Ok(()) => return,
std::result::Result::Err(value) => value,
};
assert_eq!(pending_error.context()[0].value(), "runtime_resources.hydration_pending_capacity_insufficient");
let concurrency_error = match super::validate_hydration_fairness_capacity(8, 2, 3) {
std::result::Result::Ok(()) => return,
std::result::Result::Err(value) => value,
};
assert_eq!(concurrency_error.context()[0].value(), "runtime_resources.hydration_concurrency_insufficient");
let pending_limits = [super::hydration_pending_limit(8, 3, 0), super::hydration_pending_limit(8, 3, 1), super::hydration_pending_limit(8, 3, 2)];
assert_eq!(pending_limits, [3, 3, 2]);
assert_eq!(pending_limits.iter().copied().sum::<usize>(), 8);
assert!(pending_limits.iter().copied().all(|limit| return limit >= 1));
let in_flight_limits = [super::hydration_in_flight_limit(5, 3, 0), super::hydration_in_flight_limit(5, 3, 1), super::hydration_in_flight_limit(5, 3, 2)];
assert_eq!(in_flight_limits, [2, 2, 1]);
assert_eq!(in_flight_limits.iter().copied().sum::<usize>(), 5);
assert!(in_flight_limits.iter().copied().all(|limit| return limit >= 1));
assert!(super::validate_hydration_fairness_capacity(1, 1, 0).is_ok());
assert_eq!(super::hydration_pending_limit(1, 0, 0), 0);
assert_eq!(super::hydration_in_flight_limit(1, 0, 0), 0);
return;
}
#[test]
fn v0_3_13_pre_009_duplicate_hydration_storm_keeps_one_global_key_and_distinct_keys_bounded() {
let network = match ksp_store_lib::RawNetworkId::new("devnet") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = super::RawTransactionIngestGlobalHydrationRegistry::new(2, 1);
let first_key = super::RawTransactionIngestHydrationKey {
commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed.as_str(),
network: network.clone(),
signature: ksp_store_lib::RawTransactionSignature::new([71_u8; 64]),
};
for index in 0..32 {
let subscribed = registry.subscribe_or_lead(&first_key);
let (leader, _receiver) = match subscribed {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(leader, index == 0);
}
let second_key = super::RawTransactionIngestHydrationKey {
commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed.as_str(),
network: network.clone(),
signature: ksp_store_lib::RawTransactionSignature::new([72_u8; 64]),
};
let third_key = super::RawTransactionIngestHydrationKey {
commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed.as_str(),
network,
signature: ksp_store_lib::RawTransactionSignature::new([73_u8; 64]),
};
assert!(matches!(registry.subscribe_or_lead(&second_key), std::result::Result::Ok((true, _))));
let saturated = registry.subscribe_or_lead(&third_key);
let error = match saturated {
std::result::Result::Ok(_) => return,
std::result::Result::Err(value) => value,
};
assert_eq!(error.code(), crate::ERROR_CODE_RAW_TRANSACTION_INGEST_RUNTIME_INVALID);
assert_eq!(error.context()[0].value(), "source.global_hydration_pending_saturated");
return;
}
#[tokio::test(flavor = "current_thread")]
async fn v0_3_13_pre_009_global_hydration_permit_and_leader_cleanup_are_bounded_and_fail_closed() {
let network = match ksp_store_lib::RawNetworkId::new("devnet") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let registry = std::sync::Arc::new(super::RawTransactionIngestGlobalHydrationRegistry::new(4, 1));
let first_permit = std::sync::Arc::clone(&registry.hydration_permits).try_acquire_owned();
let first_permit = match first_permit {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert!(std::sync::Arc::clone(&registry.hydration_permits).try_acquire_owned().is_err());
std::mem::drop(first_permit);
assert!(std::sync::Arc::clone(&registry.hydration_permits).try_acquire_owned().is_ok());
let key = super::RawTransactionIngestHydrationKey {
commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed.as_str(),
network,
signature: ksp_store_lib::RawTransactionSignature::new([74_u8; 64]),
};
let subscribed = registry.subscribe_or_lead(&key);
let (leader, receiver) = match subscribed {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert!(leader);
{
let _guard = super::RawTransactionIngestHydrationLeaderGuard::new(std::sync::Arc::clone(&registry), key.clone());
}
let published = receiver.borrow().clone();
assert!(matches!(published, std::option::Option::Some(super::RawTransactionIngestSharedHydrationResult::Failed(_))));
let resubscribed = registry.subscribe_or_lead(&key);
assert!(matches!(resubscribed, std::result::Result::Ok((true, _))));
return;
}