v0.3.12-pre.003

This commit is contained in:
2026-09-09 07:39:42 +02:00
parent 91438e8214
commit fa720d0054
9 changed files with 898 additions and 16 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs
// version: 9
// version: 10
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -11,7 +11,8 @@
//! and the caller-runtime-owned lifecycle with private child-task supervision. This tranche also
//! 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 exists, but no live stream is opened yet.
//! the first validated Yellowstone/HTTP runtime-resource contract exists and deterministically projects
//! Transaction/TransactionStatus updates into private source-neutral signals, but no live stream is opened yet.
mod admission;
mod error;

View File

@@ -1,5 +1,145 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
// version: 1
// version: 2
use sha2::Digest; // rust-rules: trait-import
const RAW_TRANSACTION_INGEST_YELLOWSTONE_FILTER_FINGERPRINT_DOMAIN: &[u8] = b"ksp.raw_transaction_ingest.yellowstone.filters.v1\0";
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum RawTransactionIngestSourceFamily {
Transaction,
TransactionStatus,
}
#[derive(Clone, Debug, Eq, PartialEq)]
struct RawTransactionIngestSourceRoute {
endpoint_id: ksp_store_lib::RawProvenanceCode,
provider: ksp_store_lib::RawProvenanceCode,
}
#[derive(Clone, Copy, Eq, PartialEq)]
struct RawTransactionIngestSourceTimestamp {
nanos: u32,
seconds: i64,
}
impl std::fmt::Debug for RawTransactionIngestSourceTimestamp {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter.debug_struct("RawTransactionIngestSourceTimestamp").field("nanos", &self.nanos).field("seconds", &self.seconds).finish();
}
}
#[derive(Clone, Eq, PartialEq)]
struct RawTransactionIngestSourceSignal {
created_at: std::option::Option<RawTransactionIngestSourceTimestamp>,
family: RawTransactionIngestSourceFamily,
matched_filter_count: usize,
matched_filter_fingerprint: [u8; 32],
network: ksp_store_lib::RawNetworkId,
route: RawTransactionIngestSourceRoute,
signature: ksp_store_lib::RawTransactionSignature,
slot: u64,
transaction_index: std::option::Option<u64>,
}
impl std::fmt::Debug for RawTransactionIngestSourceSignal {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter
.debug_struct("RawTransactionIngestSourceSignal")
.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("network", &self.network)
.field("route", &self.route)
.field("signature_bytes", &self.signature.as_bytes().len())
.field("slot", &self.slot)
.field("has_transaction_index", &self.transaction_index.is_some())
.finish_non_exhaustive();
}
}
trait RawTransactionIngestYellowstoneSignalView {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp>;
fn family(&self) -> RawTransactionIngestSourceFamily;
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName];
fn index(&self) -> u64;
fn signature(&self) -> ksp_onchain_transport_lib::YellowstoneTransactionSignature;
fn slot(&self) -> u64;
}
impl RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionUpdate {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return ksp_onchain_transport_lib::YellowstoneTransactionUpdate::created_at(self);
}
fn family(&self) -> RawTransactionIngestSourceFamily {
return RawTransactionIngestSourceFamily::Transaction;
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return ksp_onchain_transport_lib::YellowstoneTransactionUpdate::filters(self);
}
fn index(&self) -> u64 {
return ksp_onchain_transport_lib::YellowstoneTransactionUpdate::transaction(self).index();
}
fn signature(&self) -> ksp_onchain_transport_lib::YellowstoneTransactionSignature {
return ksp_onchain_transport_lib::YellowstoneTransactionUpdate::transaction(self).signature();
}
fn slot(&self) -> u64 {
return ksp_onchain_transport_lib::YellowstoneTransactionUpdate::slot(self);
}
}
impl RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate::created_at(self);
}
fn family(&self) -> RawTransactionIngestSourceFamily {
return RawTransactionIngestSourceFamily::TransactionStatus;
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate::filters(self);
}
fn index(&self) -> u64 {
return ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate::index(self);
}
fn signature(&self) -> ksp_onchain_transport_lib::YellowstoneTransactionSignature {
return ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate::signature(self);
}
fn slot(&self) -> u64 {
return ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate::slot(self);
}
}
impl std::convert::From<(&crate::RawTransactionIngestYellowstoneSource, &ksp_onchain_transport_lib::YellowstoneTransactionUpdate)>
for RawTransactionIngestSourceSignal
{
fn from(value: (&crate::RawTransactionIngestYellowstoneSource, &ksp_onchain_transport_lib::YellowstoneTransactionUpdate)) -> Self {
return project_yellowstone_signal(value.0, value.1);
}
}
impl std::convert::From<(&crate::RawTransactionIngestYellowstoneSource, &ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate)>
for RawTransactionIngestSourceSignal
{
fn from(value: (&crate::RawTransactionIngestYellowstoneSource, &ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate)) -> Self {
return project_yellowstone_signal(value.0, value.1);
}
}
/// Validated Yellowstone plus HTTP runtime source owned by the continuous RAW transaction ingest Worker.
///
@@ -10,6 +150,8 @@ pub struct RawTransactionIngestYellowstoneSource {
subscribe_request: ksp_onchain_transport_lib::YellowstoneSubscribeRequest,
http_pool: ksp_onchain_transport_lib::HttpTransportPool,
hydration_role: ksp_onchain_transport_lib::HttpRoleName,
network: ksp_store_lib::RawNetworkId,
route: RawTransactionIngestSourceRoute,
}
impl crate::RawTransactionIngestYellowstoneSource {
@@ -33,11 +175,23 @@ impl crate::RawTransactionIngestYellowstoneSource {
return std::result::Result::Err(crate::runtime_error("runtime_resources.hydration_commitment_invalid"));
},
}
let network = match ksp_store_lib::RawNetworkId::new(yellowstone_channel.cluster().as_str()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::result::Result::Err(crate::runtime_error("runtime_resources.yellowstone_network_unrepresentable")),
};
let provider = match ksp_store_lib::RawProvenanceCode::new(yellowstone_channel.provider().as_str()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::result::Result::Err(crate::runtime_error("runtime_resources.yellowstone_provider_unrepresentable")),
};
let endpoint_id = match ksp_store_lib::RawProvenanceCode::new(yellowstone_channel.endpoint_name()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::result::Result::Err(crate::runtime_error("runtime_resources.yellowstone_endpoint_unrepresentable")),
};
let method = match ksp_onchain_transport_lib::find_http_rpc_method("getTransaction") {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::result::Result::Err(crate::runtime_error("runtime_resources.hydration_method_missing")),
};
let compatible_http_routes = compatible_http_route_count(&http_pool, &hydration_role, method.request_kind(), yellowstone_channel.cluster().as_str());
let compatible_http_routes = compatible_http_route_count(&http_pool, &hydration_role, method.request_kind(), network.as_str());
let compatible_http_routes = match compatible_http_routes {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
@@ -45,7 +199,8 @@ impl crate::RawTransactionIngestYellowstoneSource {
if compatible_http_routes == 0 {
return std::result::Result::Err(crate::runtime_error("runtime_resources.hydration_role_unsupported"));
}
return std::result::Result::Ok(Self { yellowstone_channel, subscribe_request, http_pool, hydration_role });
let route = RawTransactionIngestSourceRoute { endpoint_id, provider };
return std::result::Result::Ok(Self { yellowstone_channel, subscribe_request, http_pool, hydration_role, network, route });
}
}
@@ -56,7 +211,7 @@ impl std::fmt::Debug for crate::RawTransactionIngestYellowstoneSource {
.debug_struct("RawTransactionIngestYellowstoneSource")
.field("yellowstone_endpoint_name", &self.yellowstone_channel.endpoint_name())
.field("yellowstone_provider", &self.yellowstone_channel.provider().as_str())
.field("network", &self.yellowstone_channel.cluster().as_str())
.field("network", &self.network.as_str())
.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())
@@ -85,7 +240,7 @@ impl crate::RawTransactionIngestRuntimeResources {
/// Validates that caller-owned Worker settings target the same logical network as the composed Yellowstone/HTTP source.
pub(crate) fn validate_network(&self, network: &ksp_store_lib::RawNetworkId) -> ksp_core_lib::Result<()> {
if self.yellowstone_source.yellowstone_channel.cluster().as_str() != network.as_str() {
if &self.yellowstone_source.network != network {
return std::result::Result::Err(crate::runtime_error("runtime_resources.worker_network_mismatch"));
}
return std::result::Result::Ok(());
@@ -131,6 +286,41 @@ fn ingestion_filter_count(request: &ksp_onchain_transport_lib::YellowstoneSubscr
return request.transaction_filter_count().saturating_add(request.transaction_status_filter_count()).saturating_add(request.block_filter_count());
}
fn matched_filter_fingerprint(filters: &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName]) -> [u8; 32] {
let mut names = filters.iter().map(ksp_onchain_transport_lib::YellowstoneSubscribeFilterName::as_str).collect::<std::vec::Vec<_>>();
names.sort_unstable();
names.dedup();
let mut hasher = sha2::Sha256::new();
hasher.update(RAW_TRANSACTION_INGEST_YELLOWSTONE_FILTER_FINGERPRINT_DOMAIN);
hasher.update((names.len() as u64).to_be_bytes());
for name in names {
hasher.update((name.len() as u64).to_be_bytes());
hasher.update(name.as_bytes());
}
return hasher.finalize().into();
}
fn project_yellowstone_signal<T: RawTransactionIngestYellowstoneSignalView>(
source: &crate::RawTransactionIngestYellowstoneSource,
update: &T,
) -> RawTransactionIngestSourceSignal {
let signature = ksp_store_lib::RawTransactionSignature::new(*update.signature().as_bytes());
let created_at = update.created_at().map(|value| {
return RawTransactionIngestSourceTimestamp { nanos: value.nanos(), seconds: value.seconds() };
});
return RawTransactionIngestSourceSignal {
created_at,
family: update.family(),
matched_filter_count: update.filters().len(),
matched_filter_fingerprint: matched_filter_fingerprint(update.filters()),
network: source.network.clone(),
route: source.route.clone(),
signature,
slot: update.slot(),
transaction_index: std::option::Option::Some(update.index()),
};
}
#[cfg(test)]
#[path = "../unit_tests/runtime_resources.rs"]
mod tests;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/dependency_boundary.rs
// version: 9
// version: 10
//! Dependency firewall canaries for the RAW transaction ingest Worker foundation.
@@ -63,6 +63,51 @@ fn v0_3_12_pre_002_manifest_opens_only_the_onchain_transport_live_source_edge()
return;
}
#[test]
fn v0_3_12_pre_003_transaction_and_status_adapters_are_private_offline_and_transport_facade_only() {
let root = include_str!("../src/lib.rs");
let resources = include_str!("../src/runtime_resources.rs");
for required in [
"RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionUpdate",
"RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate",
"YellowstoneTransactionUpdate::transaction(self).signature()",
"YellowstoneTransactionUpdate::transaction(self).index()",
"YellowstoneTransactionStatusUpdate::signature(self)",
"YellowstoneTransactionStatusUpdate::index(self)",
"RawTransactionSignature::new",
"matched_filter_fingerprint",
"yellowstone_provider_unrepresentable",
"yellowstone_endpoint_unrepresentable",
] {
assert!(resources.contains(required), "required pre.003 signal-adapter contract missing: {required}");
}
for forbidden in [
"pub struct RawTransactionIngestSourceSignal",
"pub(crate) struct RawTransactionIngestSourceSignal",
"pub use self::runtime_resources::RawTransactionIngestSourceSignal",
"open_standard_subscribe",
"next_update",
"get_transaction_observed",
"get_block_observed",
"ksp_store_postgres_lib::",
"reqwest::",
"tonic::",
"yellowstone_grpc_proto::",
] {
assert!(!resources.contains(forbidden) && !root.contains(forbidden), "pre.003 crossed a private/offline boundary: {forbidden}");
}
let status_impl =
match resources.split_once("impl RawTransactionIngestYellowstoneSignalView for ksp_onchain_transport_lib::YellowstoneTransactionStatusUpdate") {
std::option::Option::Some((_, tail)) => match tail.split_once("impl std::convert::From<") {
std::option::Option::Some((value, _)) => value,
std::option::Option::None => tail,
},
std::option::Option::None => "",
};
assert!(!status_impl.contains("::error(self)"), "TransactionStatus remote error material must not enter the private signal");
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: 3
// version: 4
//! External public, security, redaction and release-boundary hardening canaries for `pre.010`.
@@ -278,6 +278,40 @@ fn v0_3_12_pre_002_production_sources_keep_transport_confined_to_runtime_resourc
return;
}
#[test]
fn v0_3_12_pre_003_private_signal_debug_and_shape_do_not_expose_signature_filters_or_payload() {
let root = include_str!("../src/lib.rs");
let resources = include_str!("../src/runtime_resources.rs");
assert!(resources.contains("struct RawTransactionIngestSourceSignal"));
assert!(!root.contains("RawTransactionIngestSourceSignal"));
assert!(!resources.contains(".field(\"matched_filter_fingerprint\", &self.matched_filter_fingerprint)"));
assert!(!resources.contains(".field(\"signature\", &self.signature)"));
let signal_struct = match resources.split_once("struct RawTransactionIngestSourceSignal {") {
std::option::Option::Some((_, tail)) => match tail.split_once("}\n\nimpl std::fmt::Debug for RawTransactionIngestSourceSignal") {
std::option::Option::Some((value, _)) => value,
std::option::Option::None => "",
},
std::option::Option::None => "",
};
for forbidden in ["transaction:", "meta:", "error:", "payload:", "body:", "is_vote:"] {
assert!(!signal_struct.contains(forbidden), "payload/provider-specific field leaked into private source signal: {forbidden}");
}
for required in [
"created_at:",
"family:",
"matched_filter_count:",
"matched_filter_fingerprint:",
"network:",
"route:",
"signature:",
"slot:",
"transaction_index:",
] {
assert!(signal_struct.contains(required), "required private signal field missing: {required}");
}
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: 2
// version: 3
//! Release-completeness canaries through the `pre.010` public/release/security hardening tranche.
@@ -98,6 +98,7 @@ fn pre_010_external_hardening_suite_is_present_and_scoped() {
"pre_010_external_error_codes_are_stable_unique_and_domain_scoped",
"pre_010_debug_and_settings_errors_redact_worker_identity_and_invalid_values",
"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",
"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",
@@ -111,6 +112,7 @@ fn pre_010_external_hardening_suite_is_present_and_scoped() {
assert!(dependency_boundary.contains("pre_002_manifest_dependency_surface_is_exact"));
assert!(dependency_boundary.contains("v0_3_12_pre_002_source_surface_hardens_shutdown_and_faults_without_backend_or_premature_live_io"));
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"));
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,15 +1,23 @@
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
// version: 1
// version: 2
fn grpc_endpoint(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider");
}
fn grpc_endpoint_with_identity(
cluster: &str,
endpoint_name: &str,
provider: &str,
) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
let url = match ksp_onchain_transport_lib::YellowstoneGrpcEndpointUrl::parse("http://127.0.0.1:10000/GRPC-SECRET-CANARY") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
return std::option::Option::Some(ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings::new(
"yellowstone-fixture",
endpoint_name,
true,
ksp_onchain_transport_lib::YellowstoneGrpcProviderName::new("fixture-provider"),
ksp_onchain_transport_lib::YellowstoneGrpcProviderName::new(provider),
ksp_onchain_transport_lib::YellowstoneGrpcClusterName::new(cluster),
url,
ksp_onchain_transport_lib::YellowstoneGrpcSessionSettings::default(),
@@ -69,6 +77,76 @@ fn transaction_request(
return std::option::Option::Some(request);
}
struct SignalViewFixture {
created_at: std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp>,
family: super::RawTransactionIngestSourceFamily,
filters: std::vec::Vec<ksp_onchain_transport_lib::YellowstoneSubscribeFilterName>,
index: u64,
signature: ksp_onchain_transport_lib::YellowstoneTransactionSignature,
slot: u64,
}
impl super::RawTransactionIngestYellowstoneSignalView for SignalViewFixture {
fn created_at(&self) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneUpdateTimestamp> {
return self.created_at;
}
fn family(&self) -> super::RawTransactionIngestSourceFamily {
return self.family;
}
fn filters(&self) -> &[ksp_onchain_transport_lib::YellowstoneSubscribeFilterName] {
return self.filters.as_slice();
}
fn index(&self) -> u64 {
return self.index;
}
fn signature(&self) -> ksp_onchain_transport_lib::YellowstoneTransactionSignature {
return self.signature;
}
fn slot(&self) -> u64 {
return self.slot;
}
}
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 {
let filter = match ksp_onchain_transport_lib::YellowstoneSubscribeFilterName::new(*value) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
filters.push(filter);
}
return std::option::Option::Some(filters);
}
fn signal_source() -> 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("devnet", "hydration", "get_transaction") {
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,
};
}
#[tokio::test(flavor = "current_thread")]
async fn pre_002_source_accepts_matching_confirmed_transaction_and_get_transaction_route_without_io() {
let endpoint = match grpc_endpoint("devnet") {
@@ -250,3 +328,149 @@ async fn pre_002_runtime_resources_reject_worker_network_mismatch_without_starti
assert!(error.context().iter().any(|context| return context.value() == "runtime_resources.worker_network_mismatch"));
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_003_transaction_signal_fixture_preserves_exact_source_neutral_identity() {
let source = match signal_source() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let filters = match filter_names(&["filter-b", "filter-a", "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_123, 456_000_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let fixture = SignalViewFixture {
created_at: std::option::Option::Some(created_at),
family: super::RawTransactionIngestSourceFamily::Transaction,
filters,
index: 7,
signature: ksp_onchain_transport_lib::YellowstoneTransactionSignature::new([0xAB; 64]),
slot: 42,
};
let signal = super::project_yellowstone_signal(&source, &fixture);
assert_eq!(signal.family, super::RawTransactionIngestSourceFamily::Transaction);
assert_eq!(signal.network.as_str(), "devnet");
assert_eq!(signal.signature.as_bytes(), &[0xAB; 64]);
assert_eq!(signal.slot, 42);
assert_eq!(signal.transaction_index, std::option::Option::Some(7));
assert_eq!(signal.route.provider.as_str(), "fixture-provider");
assert_eq!(signal.route.endpoint_id.as_str(), "yellowstone-fixture");
assert_eq!(signal.matched_filter_count, 3);
assert_eq!(
signal.matched_filter_fingerprint,
[
0x20, 0x83, 0x1d, 0xc8, 0x37, 0x8b, 0x60, 0x70, 0xf9, 0x1d, 0x9d, 0xe6, 0xd3, 0xa1, 0xd2, 0xb3, 0xd7, 0x72, 0x98, 0xe3, 0xad, 0xa7, 0x6c, 0x01,
0xfa, 0xa3, 0x08, 0x26, 0xff, 0xab, 0xcd, 0x84,
]
);
assert_eq!(signal.created_at, std::option::Option::Some(super::RawTransactionIngestSourceTimestamp { nanos: 456_000_000, seconds: 1_760_000_123 }));
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_003_transaction_status_signal_has_no_payload_or_remote_error_material() {
let source = match signal_source() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let filters = match filter_names(&["status-secret-canary"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let fixture = SignalViewFixture {
created_at: std::option::Option::None,
family: super::RawTransactionIngestSourceFamily::TransactionStatus,
filters,
index: 9,
signature: ksp_onchain_transport_lib::YellowstoneTransactionSignature::new([0xCD; 64]),
slot: 84,
};
let signal = super::project_yellowstone_signal(&source, &fixture);
assert_eq!(signal.family, super::RawTransactionIngestSourceFamily::TransactionStatus);
assert_eq!(signal.signature.as_bytes(), &[0xCD; 64]);
assert_eq!(signal.slot, 84);
assert_eq!(signal.transaction_index, std::option::Option::Some(9));
assert_eq!(signal.created_at, std::option::Option::None);
let debug = std::format!("{signal:?}");
assert!(!debug.contains("status-secret-canary"));
assert!(debug.contains("signature_bytes"));
assert!(!debug.contains("YellowstoneTransactionError"));
assert!(!debug.contains("transaction_body"));
assert!(!debug.contains("transaction_meta"));
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_003_filter_fingerprint_is_order_and_duplicate_insensitive() {
let source = match signal_source() {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let first_filters = match filter_names(&["filter-b", "filter-a", "filter-a"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let second_filters = match filter_names(&["filter-a", "filter-b"]) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let first = SignalViewFixture {
created_at: std::option::Option::None,
family: super::RawTransactionIngestSourceFamily::Transaction,
filters: first_filters,
index: 1,
signature: ksp_onchain_transport_lib::YellowstoneTransactionSignature::new([1; 64]),
slot: 1,
};
let second = SignalViewFixture {
created_at: std::option::Option::None,
family: super::RawTransactionIngestSourceFamily::Transaction,
filters: second_filters,
index: 1,
signature: ksp_onchain_transport_lib::YellowstoneTransactionSignature::new([1; 64]),
slot: 1,
};
let first_signal = super::project_yellowstone_signal(&source, &first);
let second_signal = super::project_yellowstone_signal(&source, &second);
assert_eq!(first_signal.matched_filter_fingerprint, second_signal.matched_filter_fingerprint);
assert_eq!(first_signal.matched_filter_count, 3);
assert_eq!(second_signal.matched_filter_count, 2);
return;
}
#[tokio::test(flavor = "current_thread")]
async fn pre_003_source_rejects_route_identity_that_cannot_become_safe_provenance() {
for (endpoint_name, provider, expected_condition) in [
("yellowstone-fixture", "fixture/provider", "runtime_resources.yellowstone_provider_unrepresentable"),
("yellowstone/fixture", "fixture-provider", "runtime_resources.yellowstone_endpoint_unrepresentable"),
] {
let endpoint = match grpc_endpoint_with_identity("devnet", endpoint_name, provider) {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let channel = match ksp_onchain_transport_lib::YellowstoneGrpcChannel::prepare(&endpoint) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
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,
};
let pool = match http_pool("devnet", "hydration", "get_transaction") {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let result = crate::RawTransactionIngestYellowstoneSource::new(channel, request, pool, ksp_onchain_transport_lib::HttpRoleName::new("hydration"));
let error = match result {
std::result::Result::Ok(_) => return,
std::result::Result::Err(error) => error,
};
assert_eq!(error.code(), crate::ERROR_CODE_RAW_TRANSACTION_INGEST_RUNTIME_INVALID);
assert!(error.context().iter().any(|context| return context.value() == expected_condition));
}
return;
}