v0.3.12-pre.005

This commit is contained in:
2026-09-09 12:45:29 +02:00
parent df1dbbb8fb
commit 3a8fa87acb
9 changed files with 846 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs
// version: 11
// version: 12
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -12,8 +12,9 @@
//! owns bounded source-neutral admission, common RAW canonicalization/assembly and backend-neutral
//! Store persistence in normal mode plus concrete latest-value snapshots projected onto Worker API;
//! the first validated Yellowstone/HTTP runtime-resource contract also closes the deterministic hydration
//! qualification path in test configuration. Transaction/TransactionStatus signal projection and HTTP hydration
//! remain inactive in production until the productive source task is wired; no live stream is opened yet.
//! qualification path in test configuration. Transaction/TransactionStatus/Block signal projection, BlockMeta/Slot
//! continuity projection and HTTP hydration remain inactive in production until the productive source task is wired;
//! no live stream is opened yet.
mod admission;
mod error;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
// version: 5
// version: 6
#[cfg(test)]
use sha2::Digest; // rust-rules: trait-import
@@ -14,10 +14,64 @@ const RAW_TRANSACTION_INGEST_YELLOWSTONE_HTTP_SOURCE_KEY_DOMAIN: &[u8] = b"ksp.r
#[cfg(test)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum RawTransactionIngestSourceFamily {
Block,
Transaction,
TransactionStatus,
}
#[cfg(test)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum RawTransactionIngestContinuityFamily {
BlockMeta,
Slot,
}
#[cfg(test)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum RawTransactionIngestContinuityStatus {
Completed,
Confirmed,
CreatedBank,
Dead,
Finalized,
FirstShredReceived,
Processed,
}
#[cfg(test)]
#[derive(Clone, Eq, PartialEq)]
struct RawTransactionIngestContinuitySignal {
created_at: std::option::Option<RawTransactionIngestSourceTimestamp>,
family: RawTransactionIngestContinuityFamily,
matched_filter_count: usize,
matched_filter_fingerprint: [u8; 32],
matched_filter_id: std::option::Option<ksp_store_lib::RawProvenanceCode>,
network: ksp_store_lib::RawNetworkId,
parent_slot: std::option::Option<u64>,
route: RawTransactionIngestSourceRoute,
slot: u64,
status: std::option::Option<RawTransactionIngestContinuityStatus>,
}
#[cfg(test)]
impl std::fmt::Debug for RawTransactionIngestContinuitySignal {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter
.debug_struct("RawTransactionIngestContinuitySignal")
.field("created_at", &self.created_at)
.field("family", &self.family)
.field("matched_filter_count", &self.matched_filter_count)
.field("matched_filter_fingerprint_bytes", &self.matched_filter_fingerprint.len())
.field("has_direct_filter_id", &self.matched_filter_id.is_some())
.field("network", &self.network)
.field("parent_slot", &self.parent_slot)
.field("route", &self.route)
.field("slot", &self.slot)
.field("status", &self.status)
.finish_non_exhaustive();
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
struct RawTransactionIngestSourceRoute {
endpoint_id: ksp_store_lib::RawProvenanceCode,
@@ -141,6 +195,115 @@ impl RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::Ye
}
}
#[cfg(test)]
trait RawTransactionIngestYellowstoneBlockView {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp>;
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName];
fn slot(&self) -> u64;
fn transaction_count(&self) -> usize;
fn transaction_identity(&self, position: usize) -> ksp_core_lib::Result<(ksp_onchain_transport_lib::YellowstoneTransactionSignature, u64)>;
}
#[cfg(test)]
impl RawTransactionIngestYellowstoneBlockView for ksp_onchain_transport_lib::YellowstoneBlockUpdate {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return ksp_onchain_transport_lib::YellowstoneBlockUpdate::created_at(self);
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return ksp_onchain_transport_lib::YellowstoneBlockUpdate::filters(self);
}
fn slot(&self) -> u64 {
return ksp_onchain_transport_lib::YellowstoneBlockUpdate::slot(self);
}
fn transaction_count(&self) -> usize {
return ksp_onchain_transport_lib::YellowstoneBlockUpdate::transactions(self).len();
}
fn transaction_identity(&self, position: usize) -> ksp_core_lib::Result<(ksp_onchain_transport_lib::YellowstoneTransactionSignature, u64)> {
let transaction = match ksp_onchain_transport_lib::YellowstoneBlockUpdate::transactions(self).get(position) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::result::Result::Err(crate::runtime_error("source.block_transaction_missing")),
};
return std::result::Result::Ok((transaction.signature(), transaction.index()));
}
}
#[cfg(test)]
trait RawTransactionIngestYellowstoneContinuityView {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp>;
fn family(&self) -> RawTransactionIngestContinuityFamily;
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName];
fn parent_slot(&self) -> std::option::Option<u64>;
fn slot(&self) -> u64;
fn status(&self) -> std::option::Option<RawTransactionIngestContinuityStatus>;
}
#[cfg(test)]
impl RawTransactionIngestYellowstoneContinuityView for ksp_onchain_transport_lib::YellowstoneBlockMetaUpdate {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return ksp_onchain_transport_lib::YellowstoneBlockMetaUpdate::created_at(self);
}
fn family(&self) -> RawTransactionIngestContinuityFamily {
return RawTransactionIngestContinuityFamily::BlockMeta;
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return ksp_onchain_transport_lib::YellowstoneBlockMetaUpdate::filters(self);
}
fn parent_slot(&self) -> std::option::Option<u64> {
return std::option::Option::Some(ksp_onchain_transport_lib::YellowstoneBlockMetaUpdate::parent_slot(self));
}
fn slot(&self) -> u64 {
return ksp_onchain_transport_lib::YellowstoneBlockMetaUpdate::slot(self);
}
fn status(&self) -> std::option::Option<RawTransactionIngestContinuityStatus> {
return std::option::Option::None;
}
}
#[cfg(test)]
impl RawTransactionIngestYellowstoneContinuityView for ksp_onchain_transport_lib::YellowstoneSlotUpdate {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return ksp_onchain_transport_lib::YellowstoneSlotUpdate::created_at(self);
}
fn family(&self) -> RawTransactionIngestContinuityFamily {
return RawTransactionIngestContinuityFamily::Slot;
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return ksp_onchain_transport_lib::YellowstoneSlotUpdate::filters(self);
}
fn parent_slot(&self) -> std::option::Option<u64> {
return ksp_onchain_transport_lib::YellowstoneSlotUpdate::parent(self);
}
fn slot(&self) -> u64 {
return ksp_onchain_transport_lib::YellowstoneSlotUpdate::slot(self);
}
fn status(&self) -> std::option::Option<RawTransactionIngestContinuityStatus> {
return std::option::Option::Some(map_yellowstone_slot_status(ksp_onchain_transport_lib::YellowstoneSlotUpdate::status(self)));
}
}
#[cfg(test)]
impl std::convert::From<(&crate::RawTransactionIngestYellowstoneSource, &ksp_onchain_transport_lib::YellowstoneTransactionUpdate)>
for RawTransactionIngestSourceSignal
@@ -234,6 +397,8 @@ impl std::fmt::Debug for crate::RawTransactionIngestYellowstoneSource {
.field("transaction_filter_count", &self.subscribe_request.transaction_filter_count())
.field("transaction_status_filter_count", &self.subscribe_request.transaction_status_filter_count())
.field("block_filter_count", &self.subscribe_request.block_filter_count())
.field("blocks_meta_filter_count", &self.subscribe_request.blocks_meta_filter_count())
.field("slot_filter_count", &self.subscribe_request.slot_filter_count())
.field("commitment", &self.subscribe_request.commitment())
.field("has_from_slot", &self.subscribe_request.from_slot().is_some())
.field("hydration_role", &self.hydration_role.as_str())
@@ -361,6 +526,80 @@ fn matched_filter_fingerprint(filters: &[ksp_onchain_transport_lib::YellowstoneS
return hasher.finalize().into();
}
#[cfg(test)]
fn project_yellowstone_block_signals<T: RawTransactionIngestYellowstoneBlockView>(
source: &crate::RawTransactionIngestYellowstoneSource,
update: &T,
) -> ksp_core_lib::Result<std::vec::Vec<RawTransactionIngestSourceSignal>> {
let filters = update.filters();
let matched_filter_count = filters.len();
let matched_filter_fingerprint = matched_filter_fingerprint(filters);
let matched_filter_id = matched_filter_direct_id(filters);
let created_at = map_yellowstone_source_timestamp(update.created_at());
let mut signals = std::vec::Vec::with_capacity(update.transaction_count());
for position in 0..update.transaction_count() {
let (signature, transaction_index) = match update.transaction_identity(position) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
signals.push(RawTransactionIngestSourceSignal {
created_at,
family: RawTransactionIngestSourceFamily::Block,
matched_filter_count,
matched_filter_fingerprint,
matched_filter_id: matched_filter_id.clone(),
network: source.network.clone(),
route: source.route.clone(),
signature: ksp_store_lib::RawTransactionSignature::new(signature.into_bytes()),
slot: update.slot(),
transaction_index: std::option::Option::Some(transaction_index),
});
}
return std::result::Result::Ok(signals);
}
#[cfg(test)]
fn project_yellowstone_continuity_signal<T: RawTransactionIngestYellowstoneContinuityView>(
source: &crate::RawTransactionIngestYellowstoneSource,
update: &T,
) -> RawTransactionIngestContinuitySignal {
let filters = update.filters();
return RawTransactionIngestContinuitySignal {
created_at: map_yellowstone_source_timestamp(update.created_at()),
family: update.family(),
matched_filter_count: filters.len(),
matched_filter_fingerprint: matched_filter_fingerprint(filters),
matched_filter_id: matched_filter_direct_id(filters),
network: source.network.clone(),
parent_slot: update.parent_slot(),
route: source.route.clone(),
slot: update.slot(),
status: update.status(),
};
}
#[cfg(test)]
fn map_yellowstone_slot_status(status: ksp_onchain_transport_lib::YellowstoneSlotStatus) -> RawTransactionIngestContinuityStatus {
return match status {
ksp_onchain_transport_lib::YellowstoneSlotStatus::Processed => RawTransactionIngestContinuityStatus::Processed,
ksp_onchain_transport_lib::YellowstoneSlotStatus::Confirmed => RawTransactionIngestContinuityStatus::Confirmed,
ksp_onchain_transport_lib::YellowstoneSlotStatus::Finalized => RawTransactionIngestContinuityStatus::Finalized,
ksp_onchain_transport_lib::YellowstoneSlotStatus::FirstShredReceived => RawTransactionIngestContinuityStatus::FirstShredReceived,
ksp_onchain_transport_lib::YellowstoneSlotStatus::Completed => RawTransactionIngestContinuityStatus::Completed,
ksp_onchain_transport_lib::YellowstoneSlotStatus::CreatedBank => RawTransactionIngestContinuityStatus::CreatedBank,
ksp_onchain_transport_lib::YellowstoneSlotStatus::Dead => RawTransactionIngestContinuityStatus::Dead,
};
}
#[cfg(test)]
fn map_yellowstone_source_timestamp(
created_at: std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp>,
) -> std::option::Option<RawTransactionIngestSourceTimestamp> {
return created_at.map(|value| {
return RawTransactionIngestSourceTimestamp { nanos: value.nanos(), seconds: value.seconds() };
});
}
#[cfg(test)]
fn project_yellowstone_signal<T: RawTransactionIngestYellowstoneSignalView>(
source: &crate::RawTransactionIngestYellowstoneSource,
@@ -543,6 +782,7 @@ fn build_hydration_provenance(
#[cfg(test)]
fn hydration_method_code(family: RawTransactionIngestSourceFamily) -> &'static str {
return match family {
RawTransactionIngestSourceFamily::Block => "block_get_transaction",
RawTransactionIngestSourceFamily::Transaction => "transaction_get_transaction",
RawTransactionIngestSourceFamily::TransactionStatus => "status_get_transaction",
};

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/dependency_boundary.rs
// version: 11
// version: 12
//! Dependency firewall canaries for the RAW transaction ingest Worker foundation.
@@ -144,6 +144,38 @@ fn v0_3_12_pre_004_hydration_contract_uses_only_transport_facade_common_raw_and_
return;
}
#[test]
fn v0_3_12_pre_005_block_and_continuity_adapters_remain_private_offline_and_transport_facade_only() {
let root = include_str!("../src/lib.rs");
let resources = include_str!("../src/runtime_resources.rs");
for required in [
"RawTransactionIngestYellowstoneBlockView",
"YellowstoneBlockUpdate",
"project_yellowstone_block_signals",
"RawTransactionIngestYellowstoneContinuityView",
"YellowstoneBlockMetaUpdate",
"YellowstoneSlotUpdate",
"RawTransactionIngestContinuitySignal",
"block_get_transaction",
] {
assert!(resources.contains(required), "required pre.005 private adapter contract missing: {required}");
}
for forbidden in [
"open_standard_subscribe",
"next_update",
"get_block_observed",
"ksp_config_lib::",
"ksp_job_backfill_lib::",
"ksp_store_postgres_lib::",
"reqwest::",
"tonic::",
"yellowstone_grpc_proto::",
] {
assert!(!resources.contains(forbidden) && !root.contains(forbidden), "pre.005 crossed a forbidden boundary: {forbidden}");
}
return;
}
#[test]
fn v0_3_12_pre_002_source_surface_hardens_shutdown_and_faults_without_backend_or_premature_live_io() {
let root = include_str!("../src/lib.rs");

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
// version: 6
// version: 7
//! External public, security, redaction and release-boundary hardening canaries for `pre.010`.
@@ -338,6 +338,49 @@ fn v0_3_12_pre_004_hydration_provenance_and_remote_material_are_bounded_and_reda
return;
}
#[test]
fn v0_3_12_pre_005_block_and_continuity_shapes_are_bounded_redacted_and_raw_separated() {
let resources = include_str!("../src/runtime_resources.rs");
for required in [
"impl RawTransactionIngestYellowstoneBlockView for ksp_onchain_transport_lib::YellowstoneBlockUpdate",
"impl RawTransactionIngestYellowstoneContinuityView for ksp_onchain_transport_lib::YellowstoneBlockMetaUpdate",
"impl RawTransactionIngestYellowstoneContinuityView for ksp_onchain_transport_lib::YellowstoneSlotUpdate",
"RawTransactionIngestSourceFamily::Block",
"project_yellowstone_block_signals",
"project_yellowstone_continuity_signal",
"RawTransactionIngestContinuityStatus::Dead",
"block_get_transaction",
] {
assert!(resources.contains(required), "required pre.005 bounded adapter guard missing: {required}");
}
let continuity_struct = match resources.split_once("struct RawTransactionIngestContinuitySignal {") {
std::option::Option::Some((_, tail)) => match tail.split_once("impl std::fmt::Debug for RawTransactionIngestContinuitySignal") {
std::option::Option::Some((value, _)) => value,
std::option::Option::None => "",
},
std::option::Option::None => "",
};
for required in [
"created_at:",
"family:",
"matched_filter_count:",
"matched_filter_fingerprint:",
"matched_filter_id:",
"network:",
"parent_slot:",
"route:",
"slot:",
"status:",
] {
assert!(continuity_struct.contains(required), "required continuity-only field missing: {required}");
}
for forbidden in ["signature:", "transaction:", "meta:", "payload:", "body:", "error:", "dead_error:"] {
assert!(!continuity_struct.contains(forbidden), "RAW/remote material leaked into continuity-only signal: {forbidden}");
}
assert!(!resources.contains("YellowstoneSlotUpdate::dead_error"));
return;
}
#[test]
fn v0_3_12_pre_002_runtime_resource_contract_performs_no_live_io_or_source_spawn() {
let resources = include_str!("../src/runtime_resources.rs");

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
// version: 4
// version: 5
//! Release-completeness canaries through the `pre.010` public/release/security hardening tranche.
@@ -100,6 +100,7 @@ fn pre_010_external_hardening_suite_is_present_and_scoped() {
"v0_3_12_pre_002_manifest_dependency_surface_opens_only_transport_and_remains_backend_neutral",
"v0_3_12_pre_003_private_signal_debug_and_shape_do_not_expose_signature_filters_or_payload",
"v0_3_12_pre_004_hydration_provenance_and_remote_material_are_bounded_and_redacted",
"v0_3_12_pre_005_block_and_continuity_shapes_are_bounded_redacted_and_raw_separated",
"pre_010_source_visibility_contract_uses_crate_root_for_shared_items",
"pre_010_production_surface_has_no_historical_backfill_or_retriever_contract",
"v0_3_12_pre_002_production_sources_keep_transport_confined_to_runtime_resources",
@@ -115,6 +116,7 @@ fn pre_010_external_hardening_suite_is_present_and_scoped() {
assert!(dependency_boundary.contains("v0_3_12_pre_002_manifest_opens_only_the_onchain_transport_live_source_edge"));
assert!(dependency_boundary.contains("v0_3_12_pre_003_transaction_and_status_adapters_are_private_offline_and_transport_facade_only"));
assert!(dependency_boundary.contains("v0_3_12_pre_004_hydration_contract_uses_only_transport_facade_common_raw_and_existing_ingress"));
assert!(dependency_boundary.contains("v0_3_12_pre_005_block_and_continuity_adapters_remain_private_offline_and_transport_facade_only"));
let public_api = include_str!("public_api.rs");
assert!(public_api.contains("pre_003_kind_code_and_settings_are_consumable_from_crate_root"));
assert!(public_api.contains("pre_004_start_handle_and_terminal_future_are_consumable_without_public_join_handle"));

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
// version: 4
// version: 5
fn grpc_endpoint(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider");
@@ -112,6 +112,73 @@ impl super::RawTransactionIngestYellowstoneSignalView for SignalViewFixture {
}
}
struct BlockViewFixture {
created_at: std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp>,
filters: std::vec::Vec<ksp_onchain_transport_lib::YellowstoneSubscribeFilterName>,
slot: u64,
transactions: std::vec::Vec<(ksp_onchain_transport_lib::YellowstoneTransactionSignature, u64)>,
}
impl super::RawTransactionIngestYellowstoneBlockView for BlockViewFixture {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return self.created_at;
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return self.filters.as_slice();
}
fn slot(&self) -> u64 {
return self.slot;
}
fn transaction_count(&self) -> usize {
return self.transactions.len();
}
fn transaction_identity(&self, position: usize) -> ksp_core_lib::Result<(ksp_onchain_transport_lib::YellowstoneTransactionSignature, u64)> {
return match self.transactions.get(position) {
std::option::Option::Some(value) => std::result::Result::Ok(*value),
std::option::Option::None => std::result::Result::Err(crate::runtime_error("fixture.block_transaction_missing")),
};
}
}
struct ContinuityViewFixture {
created_at: std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp>,
family: super::RawTransactionIngestContinuityFamily,
filters: std::vec::Vec<ksp_onchain_transport_lib::YellowstoneSubscribeFilterName>,
parent_slot: std::option::Option<u64>,
slot: u64,
status: std::option::Option<super::RawTransactionIngestContinuityStatus>,
}
impl super::RawTransactionIngestYellowstoneContinuityView for ContinuityViewFixture {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return self.created_at;
}
fn family(&self) -> super::RawTransactionIngestContinuityFamily {
return self.family;
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return self.filters.as_slice();
}
fn parent_slot(&self) -> std::option::Option<u64> {
return self.parent_slot;
}
fn slot(&self) -> u64 {
return self.slot;
}
fn status(&self) -> std::option::Option<super::RawTransactionIngestContinuityStatus> {
return self.status;
}
}
fn filter_names(values: &[&str]) -> std::option::Option<std::vec::Vec<ksp_onchain_transport_lib::YellowstoneSubscribeFilterName>> {
let mut filters = std::vec::Vec::with_capacity(values.len());
for value in values {
@@ -478,6 +545,8 @@ async fn pre_002_runtime_resource_debug_is_safe_and_exposes_no_client_inner() {
let debug = std::format!("{resources:?}");
assert!(debug.contains("RawTransactionIngestRuntimeResources"));
assert!(debug.contains("devnet"));
assert!(debug.contains("blocks_meta_filter_count"));
assert!(debug.contains("slot_filter_count"));
assert!(!debug.contains("GRPC-SECRET-CANARY"));
assert!(!debug.contains("HTTP-SECRET-CANARY"));
assert!(!debug.contains("127.0.0.1"));
@@ -668,6 +737,150 @@ async fn pre_003_source_rejects_route_identity_that_cannot_become_safe_provenanc
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_005_block_projects_transaction_signals_in_exact_source_order() {
let source = match signal_source() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let filters = match filter_names(&["block-filter-b", "block-filter-a"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let created_at = match ksp_onchain_transport_lib::YellowstoneUpdateTimestamp::new(1_760_000_321, 123_000_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let fixture = BlockViewFixture {
created_at: std::option::Option::Some(created_at),
filters,
slot: 777,
transactions: std::vec![
(ksp_onchain_transport_lib::YellowstoneTransactionSignature::new([0x11; 64]), 9),
(ksp_onchain_transport_lib::YellowstoneTransactionSignature::new([0x22; 64]), 3),
(ksp_onchain_transport_lib::YellowstoneTransactionSignature::new([0x33; 64]), 17),
],
};
let signals = match super::project_yellowstone_block_signals(&source, &fixture) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(signals.len(), 3);
assert_eq!(signals[0].signature.as_bytes(), &[0x11; 64]);
assert_eq!(signals[1].signature.as_bytes(), &[0x22; 64]);
assert_eq!(signals[2].signature.as_bytes(), &[0x33; 64]);
assert_eq!(signals[0].transaction_index, std::option::Option::Some(9));
assert_eq!(signals[1].transaction_index, std::option::Option::Some(3));
assert_eq!(signals[2].transaction_index, std::option::Option::Some(17));
for signal in &signals {
assert_eq!(signal.family, super::RawTransactionIngestSourceFamily::Block);
assert_eq!(signal.slot, 777);
assert_eq!(signal.network.as_str(), "devnet");
assert_eq!(signal.matched_filter_count, 2);
assert_eq!(signal.created_at, std::option::Option::Some(super::RawTransactionIngestSourceTimestamp { nanos: 123_000_000, seconds: 1_760_000_321 }));
}
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_005_block_hydration_uses_distinct_composite_method() {
let source = match signal_source() {
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::Block, 42, 7, &["block-filter"], 0) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let received_at = match ksp_store_lib::RawTimestamp::from_unix_millis(1_760_000_124_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let provenance = match super::build_hydration_provenance(
&settings,
&signal,
"fixture-http-provider",
"http-hydration-fixture",
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
received_at,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(provenance.acquisition_method().as_str(), "block_get_transaction");
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_005_block_meta_and_slot_project_continuity_only_without_remote_dead_error() {
let source = match signal_source() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let block_filters = match filter_names(&["block-meta-filter"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let slot_filters = match filter_names(&["slot-filter-secret", "slot-filter-secret"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let block_meta = ContinuityViewFixture {
created_at: std::option::Option::None,
family: super::RawTransactionIngestContinuityFamily::BlockMeta,
filters: block_filters,
parent_slot: std::option::Option::Some(899),
slot: 900,
status: std::option::Option::None,
};
let slot = ContinuityViewFixture {
created_at: std::option::Option::None,
family: super::RawTransactionIngestContinuityFamily::Slot,
filters: slot_filters,
parent_slot: std::option::Option::Some(900),
slot: 901,
status: std::option::Option::Some(super::RawTransactionIngestContinuityStatus::Dead),
};
let block_meta_signal = super::project_yellowstone_continuity_signal(&source, &block_meta);
let slot_signal = super::project_yellowstone_continuity_signal(&source, &slot);
assert_eq!(block_meta_signal.family, super::RawTransactionIngestContinuityFamily::BlockMeta);
assert_eq!(block_meta_signal.slot, 900);
assert_eq!(block_meta_signal.parent_slot, std::option::Option::Some(899));
assert_eq!(block_meta_signal.status, std::option::Option::None);
assert_eq!(slot_signal.family, super::RawTransactionIngestContinuityFamily::Slot);
assert_eq!(slot_signal.slot, 901);
assert_eq!(slot_signal.parent_slot, std::option::Option::Some(900));
assert_eq!(slot_signal.status, std::option::Option::Some(super::RawTransactionIngestContinuityStatus::Dead));
assert_eq!(slot_signal.matched_filter_count, 2);
let debug = std::format!("{slot_signal:?}");
assert!(!debug.contains("slot-filter-secret"));
assert!(!debug.contains("dead_error"));
assert!(!debug.contains("transaction"));
assert!(!debug.contains("meta"));
assert!(!debug.contains("payload"));
return;
}
#[test]
fn pre_005_slot_status_projection_is_exact_and_source_neutral() {
for (source, expected) in [
(ksp_onchain_transport_lib::YellowstoneSlotStatus::Processed, super::RawTransactionIngestContinuityStatus::Processed),
(ksp_onchain_transport_lib::YellowstoneSlotStatus::Confirmed, super::RawTransactionIngestContinuityStatus::Confirmed),
(ksp_onchain_transport_lib::YellowstoneSlotStatus::Finalized, super::RawTransactionIngestContinuityStatus::Finalized),
(ksp_onchain_transport_lib::YellowstoneSlotStatus::FirstShredReceived, super::RawTransactionIngestContinuityStatus::FirstShredReceived),
(ksp_onchain_transport_lib::YellowstoneSlotStatus::Completed, super::RawTransactionIngestContinuityStatus::Completed),
(ksp_onchain_transport_lib::YellowstoneSlotStatus::CreatedBank, super::RawTransactionIngestContinuityStatus::CreatedBank),
(ksp_onchain_transport_lib::YellowstoneSlotStatus::Dead, super::RawTransactionIngestContinuityStatus::Dead),
] {
assert_eq!(super::map_yellowstone_slot_status(source), expected);
}
return;
}
#[test]
fn pre_004_composite_provenance_rejects_overflow_without_truncation() {
let provider = match ksp_store_lib::RawProvenanceCode::new("yellowstone-provider") {