v0.3.14-pre.007
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
|
||||
// version: 6
|
||||
// version: 7
|
||||
|
||||
/// Maximum number of slots admitted by one private continuity HTTP discovery window outside this module.
|
||||
pub(crate) const MAX_RAW_TRANSACTION_INGEST_CONTINUITY_DISCOVERY_WINDOW_SLOTS: u64 = MAX_RAW_TRANSACTION_INGEST_REPAIR_DISCOVERY_WINDOW_SLOTS;
|
||||
@@ -174,6 +174,43 @@ impl RawTransactionIngestGapRange {
|
||||
}
|
||||
}
|
||||
|
||||
/// Private run-local obligation for one transaction reference already observed by a live source.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) struct RawTransactionIngestKnownReferenceObligation {
|
||||
commitment: ksp_onchain_transport_lib::SolanaCommitment,
|
||||
reference: ksp_store_lib::RawTransactionReference,
|
||||
slot: u64,
|
||||
}
|
||||
|
||||
impl crate::RawTransactionIngestKnownReferenceObligation {
|
||||
/// Creates one known-reference obligation without inventing any absence or coverage proof.
|
||||
pub(crate) fn new(
|
||||
reference: ksp_store_lib::RawTransactionReference,
|
||||
slot: u64,
|
||||
commitment: ksp_onchain_transport_lib::SolanaCommitment,
|
||||
) -> ksp_core_lib::Result<Self> {
|
||||
if commitment == ksp_onchain_transport_lib::SolanaCommitment::Processed {
|
||||
return std::result::Result::Err(crate::runtime_error("continuity.known_reference_processed_unsupported"));
|
||||
}
|
||||
return std::result::Result::Ok(Self { commitment, reference, slot });
|
||||
}
|
||||
|
||||
/// Returns the exact commitment under which this reference must be resolved.
|
||||
pub(crate) const fn commitment(&self) -> ksp_onchain_transport_lib::SolanaCommitment {
|
||||
return self.commitment;
|
||||
}
|
||||
|
||||
/// Returns the already-known canonical transaction reference.
|
||||
pub(crate) const fn reference(&self) -> &ksp_store_lib::RawTransactionReference {
|
||||
return &self.reference;
|
||||
}
|
||||
|
||||
/// Returns the already-observed slot associated with the reference.
|
||||
pub(crate) const fn slot(&self) -> u64 {
|
||||
return self.slot;
|
||||
}
|
||||
}
|
||||
|
||||
/// Private run-local anchor for one WebSocket continuity incident.
|
||||
///
|
||||
/// The anchor never derives slots from wall-clock time. Its inclusive start is the latest slot actually observed by that source before Transport reported a
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs
|
||||
// version: 30
|
||||
// version: 31
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -119,6 +119,8 @@ pub(crate) use self::continuity::RawTransactionIngestContinuityCapabilityDescrip
|
||||
pub(crate) use self::continuity::RawTransactionIngestContinuityContracts;
|
||||
/// Private provider-neutral coverage scope used by run-local continuity proof contracts.
|
||||
pub(crate) use self::continuity::RawTransactionIngestCoverageScope;
|
||||
/// Private run-local obligation for one transaction reference already observed by a live source.
|
||||
pub(crate) use self::continuity::RawTransactionIngestKnownReferenceObligation;
|
||||
/// Private run-local WebSocket incident anchor built only from observed source slots and safe Transport counters.
|
||||
pub(crate) use self::continuity::RawTransactionIngestWebSocketIncidentAnchor;
|
||||
/// Creates one terminal content-conflict error without copying conflicting material into diagnostics.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
|
||||
// version: 32
|
||||
// version: 33
|
||||
|
||||
use sha2::Digest; // rust-rules: trait-import
|
||||
|
||||
@@ -4026,6 +4026,20 @@ struct RawTransactionIngestHydrationFetch {
|
||||
observed: RawTransactionIngestObservedTransaction,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum RawTransactionIngestKnownReferenceMissingDisposition {
|
||||
AwaitCoverage,
|
||||
PreferBlockSlot,
|
||||
}
|
||||
|
||||
enum RawTransactionIngestKnownReferenceHydrationResolution {
|
||||
Available(crate::RawTransactionIngress),
|
||||
Missing {
|
||||
disposition: RawTransactionIngestKnownReferenceMissingDisposition,
|
||||
obligation: crate::RawTransactionIngestKnownReferenceObligation,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum RawTransactionIngestSharedHydrationResult {
|
||||
Available(RawTransactionIngestObservedTransaction),
|
||||
@@ -4219,14 +4233,24 @@ impl RawTransactionIngestHydrationCoordinator {
|
||||
self.pending_signal_count -= pending.signals.len();
|
||||
for pending_signal in pending.signals {
|
||||
let signal_slot = pending_signal.signal.slot;
|
||||
let ingress = finalize_hydration(hydration, settings, pending_signal.signal, pending_signal.received_at, &fetched.observed);
|
||||
let ingress = match ingress {
|
||||
let resolution = resolve_known_reference_hydration(hydration, settings, pending_signal.signal, pending_signal.received_at, &fetched.observed);
|
||||
let resolution = match resolution {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let ingress = match ingress {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => {
|
||||
let ingress = match resolution {
|
||||
RawTransactionIngestKnownReferenceHydrationResolution::Available(value) => value,
|
||||
RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation } => {
|
||||
if obligation.commitment() != hydration.commitment
|
||||
|| obligation.reference().network() != &hydration.network
|
||||
|| obligation.slot() != signal_slot
|
||||
{
|
||||
return std::result::Result::Err(crate::runtime_error("source.known_reference_obligation_mismatch"));
|
||||
}
|
||||
match disposition {
|
||||
RawTransactionIngestKnownReferenceMissingDisposition::AwaitCoverage
|
||||
| RawTransactionIngestKnownReferenceMissingDisposition::PreferBlockSlot => {},
|
||||
}
|
||||
if let std::result::Result::Err(error) = processing_frontier.settle_pending(signal_slot) {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
@@ -4389,6 +4413,38 @@ fn shared_hydration_result(
|
||||
};
|
||||
}
|
||||
|
||||
fn resolve_known_reference_hydration(
|
||||
hydration: &RawTransactionIngestHydrationContext,
|
||||
settings: &crate::RawTransactionIngestSettings,
|
||||
signal: RawTransactionIngestSourceSignal,
|
||||
received_at: ksp_store_lib::RawTimestamp,
|
||||
observed: &RawTransactionIngestObservedTransaction,
|
||||
) -> ksp_core_lib::Result<RawTransactionIngestKnownReferenceHydrationResolution> {
|
||||
let reference = ksp_store_lib::RawTransactionReference::new(signal.network.clone(), signal.signature);
|
||||
let obligation = match crate::RawTransactionIngestKnownReferenceObligation::new(reference, signal.slot, hydration.commitment) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let ingress = finalize_hydration(hydration, settings, signal, received_at, observed);
|
||||
let ingress = match ingress {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
if let std::option::Option::Some(value) = ingress {
|
||||
return std::result::Result::Ok(RawTransactionIngestKnownReferenceHydrationResolution::Available(value));
|
||||
}
|
||||
let block_slot_supported = match http_role_supports_rpc_method(&hydration.http_pool, &hydration.hydration_role, "getBlock", hydration.network.as_str()) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let disposition = if block_slot_supported {
|
||||
RawTransactionIngestKnownReferenceMissingDisposition::PreferBlockSlot
|
||||
} else {
|
||||
RawTransactionIngestKnownReferenceMissingDisposition::AwaitCoverage
|
||||
};
|
||||
return std::result::Result::Ok(RawTransactionIngestKnownReferenceHydrationResolution::Missing { disposition, obligation });
|
||||
}
|
||||
|
||||
fn finalize_hydration(
|
||||
hydration: &RawTransactionIngestHydrationContext,
|
||||
settings: &crate::RawTransactionIngestSettings,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
|
||||
// version: 30
|
||||
// version: 31
|
||||
|
||||
//! External public, security, redaction and release-boundary hardening canaries through `v0.3.14-pre.006`.
|
||||
//! External public, security, redaction and release-boundary hardening canaries through `v0.3.14-pre.007`.
|
||||
|
||||
fn network(value: &'static str) -> std::option::Option<ksp_store_lib::RawNetworkId> {
|
||||
let result = ksp_store_lib::RawNetworkId::new(value);
|
||||
@@ -1116,3 +1116,30 @@ fn v0_3_14_pre_006_http_discovery_is_bounded_prefers_closed_range_and_never_uses
|
||||
assert!(!root.contains("repair"), "pre.006 leaked lower-case repair responsibility through crate root");
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_14_pre_007_known_reference_hydration_reuses_one_registry_and_preserves_missing_obligation() {
|
||||
let continuity = include_str!("../src/continuity.rs");
|
||||
let resources = include_str!("../src/runtime_resources.rs");
|
||||
let root = include_str!("../src/lib.rs");
|
||||
for required in [
|
||||
"RawTransactionIngestKnownReferenceObligation",
|
||||
"known_reference_processed_unsupported",
|
||||
"RawTransactionIngestKnownReferenceHydrationResolution",
|
||||
"RawTransactionIngestKnownReferenceMissingDisposition",
|
||||
"fetch_hydration_shared",
|
||||
"resolve_known_reference_hydration",
|
||||
"PreferBlockSlot",
|
||||
"AwaitCoverage",
|
||||
"get_transaction_observed",
|
||||
"http_role_supports_rpc_method",
|
||||
] {
|
||||
assert!(continuity.contains(required) || resources.contains(required), "required pre.007 known-reference guard missing: {required}");
|
||||
}
|
||||
assert_eq!(resources.matches("struct RawTransactionIngestGlobalHydrationRegistry").count(), 1);
|
||||
assert!(!resources.contains("KnownReferenceHydrationRegistry"));
|
||||
assert!(!resources.contains("known_reference_retry"));
|
||||
assert!(!root.contains("pub use self::continuity::RawTransactionIngestKnownReferenceObligation"));
|
||||
assert!(!root.contains("repair"), "pre.007 leaked lower-case repair responsibility through crate root");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
|
||||
// version: 25
|
||||
// version: 26
|
||||
|
||||
//! Release-completeness canaries through the `v0.3.14-pre.006` bounded HTTP continuity-discovery tranche.
|
||||
//! Release-completeness canaries through the `v0.3.14-pre.007` known-reference hydration tranche.
|
||||
|
||||
#[test]
|
||||
fn pre_010_production_module_inventory_is_exact() -> std::io::Result<()> {
|
||||
@@ -302,3 +302,23 @@ fn v0_3_14_pre_006_bounded_http_discovery_canaries_are_present_without_backfill_
|
||||
assert!(!root.contains("backfill"));
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_14_pre_007_known_reference_hydration_canaries_are_present_without_second_registry_or_public_surface_growth() {
|
||||
let continuity_tests = include_str!("../unit_tests/continuity.rs");
|
||||
let hardening = include_str!("hardening.rs");
|
||||
let resource_tests = include_str!("../unit_tests/runtime_resources.rs");
|
||||
let root = include_str!("../src/lib.rs");
|
||||
for required in [
|
||||
"pre_007_known_reference_obligation_preserves_exact_reference_slot_and_commitment",
|
||||
"v0_3_14_pre_007_known_reference_hydration_reuses_global_registry_and_available_material",
|
||||
"v0_3_14_pre_007_missing_known_reference_remains_open_without_block_capability",
|
||||
"v0_3_14_pre_007_missing_known_reference_prefers_same_role_block_slot_when_supported",
|
||||
] {
|
||||
assert!(continuity_tests.contains(required) || resource_tests.contains(required), "required pre.007 canary missing: {required}");
|
||||
}
|
||||
assert!(hardening.contains("v0_3_14_pre_007_known_reference_hydration_reuses_one_registry_and_preserves_missing_obligation"));
|
||||
assert!(!root.contains("pub use self::continuity::RawTransactionIngestKnownReferenceObligation"));
|
||||
assert!(!root.contains("pub use self::runtime_resources::RawTransactionIngestKnownReference"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(®istry),
|
||||
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(®istry),
|
||||
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 = [
|
||||
|
||||
Reference in New Issue
Block a user