v0.3.7-pre.007

This commit is contained in:
2026-09-02 16:07:57 +02:00
parent 6fc5b5b607
commit 9c4469248a
21 changed files with 1518 additions and 67 deletions

View File

@@ -0,0 +1,198 @@
// file: crates/ksp-app-backfill-desk/unit_tests/backfill_request.rs
// version: 1
fn ready_options() -> crate::BackfillDeskOptionsDto {
let limits = crate::backfill_request_limits();
assert!(limits.is_ok());
let limits = match limits {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => crate::BackfillRequestLimitsDto {
default_hydration_concurrency: 1,
default_max_candidates: 1,
default_max_pages: 1,
default_page_size: 1,
max_hydration_concurrency: 1,
max_candidates: 1,
max_pages: 1,
max_page_size: 1,
max_signature_text_bytes: 88,
min_signature_text_bytes: 64,
},
};
return crate::BackfillDeskOptionsDto {
commitments: crate::backfill_commitment_codes(),
composition_ready: true,
configured_networks: vec!["mainnet-beta".to_owned()],
http_routes: vec![
crate::BackfillHttpRouteOptionDto {
pooled: true,
providers: vec!["publicnode".to_owned(), "solana-public".to_owned()],
role: "backfill_pool".to_owned(),
},
crate::BackfillHttpRouteOptionDto { pooled: false, providers: vec!["publicnode".to_owned()], role: "backfill_publicnode".to_owned() },
],
limits,
network_coherent: true,
scope_kinds: crate::backfill_scope_kind_codes(),
store_diagnostic: std::option::Option::None,
store_network: std::option::Option::Some("mainnet-beta".to_owned()),
store_ready: true,
transport_diagnostic: std::option::Option::None,
transport_ready: true,
};
}
fn request(scope_kind: &str) -> crate::BackfillStartRequestDto {
return crate::BackfillStartRequestDto {
address: std::option::Option::Some("11111111111111111111111111111111".to_owned()),
anchor_signature: std::option::Option::None,
commitment: "finalized".to_owned(),
explicit_signatures: std::vec::Vec::new(),
hydration_concurrency: 4,
http_role: "backfill_pool".to_owned(),
max_candidates: 100,
max_pages: 10,
min_context_slot: std::option::Option::Some("123456".to_owned()),
page_size: 100,
scope_kind: scope_kind.to_owned(),
};
}
fn job_id() -> std::option::Option<ksp_job_api::JobId> {
let job_id = ksp_job_api::JobId::new("request-mapping-test");
assert!(job_id.is_ok());
return match job_id {
std::result::Result::Ok(value) => std::option::Option::Some(value),
std::result::Result::Err(_) => std::option::Option::None,
};
}
#[test]
fn latest_address_maps_to_backend_network_role_commitment_and_bounds() {
let job_id = job_id();
let job_id = match job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let mapped = crate::map_backfill_request(request("latest_address"), &ready_options(), job_id);
assert!(mapped.is_ok());
let mapped = match mapped {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(mapped.network().as_str(), "mainnet-beta");
assert_eq!(mapped.role().as_str(), "backfill_pool");
assert_eq!(mapped.commitment(), ksp_job_backfill_lib::BackfillCommitment::Finalized);
assert_eq!(mapped.scope().kind(), ksp_job_backfill_lib::BackfillScopeKind::LatestAddress);
assert_eq!(mapped.page_size(), 100);
assert_eq!(mapped.max_pages(), 10);
assert_eq!(mapped.max_candidates(), 100);
assert_eq!(mapped.hydration_concurrency(), 4);
assert_eq!(mapped.min_context_slot(), std::option::Option::Some(123456));
}
#[test]
fn before_and_after_scopes_require_an_exact_anchor_shape() {
for scope_kind in ["before_address", "after_address"] {
let job_id = job_id();
let job_id = match job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let mut input = request(scope_kind);
input.anchor_signature = std::option::Option::Some("1".repeat(64));
let mapped = crate::map_backfill_request(input, &ready_options(), job_id);
assert!(mapped.is_ok(), "scope {scope_kind} should map with a bounded anchor");
}
let job_id = job_id();
let job_id = match job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let missing_anchor = crate::map_backfill_request(request("before_address"), &ready_options(), job_id);
assert!(missing_anchor.is_err());
}
#[test]
fn explicit_signatures_reject_address_context_and_deduplicate_in_job_contract() {
let job_id = job_id();
let job_id = match job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let mut input = request("explicit_signatures");
input.address = std::option::Option::None;
input.min_context_slot = std::option::Option::None;
input.explicit_signatures = vec!["1".repeat(64), "1".repeat(64), "2".repeat(64)];
let mapped = crate::map_backfill_request(input, &ready_options(), job_id);
assert!(mapped.is_ok());
let mapped = match mapped {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let signatures = mapped.scope().signatures();
assert!(signatures.is_some());
if let std::option::Option::Some(signatures) = signatures {
assert_eq!(signatures.len(), 2);
}
let mut hostile = request("explicit_signatures");
hostile.address = std::option::Option::None;
hostile.min_context_slot = std::option::Option::None;
hostile.explicit_signatures = vec![" 1".to_owned()];
let hostile_job_id = job_id();
let hostile_job_id = match hostile_job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
assert!(crate::map_backfill_request(hostile, &ready_options(), hostile_job_id).is_err());
}
#[test]
fn route_inventory_and_composition_are_revalidated_before_mapping() {
let first_job_id = job_id();
let first_job_id = match first_job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let mut unknown_route = request("latest_address");
unknown_route.http_role = "provider-from-frontend".to_owned();
let rejected = crate::map_backfill_request(unknown_route, &ready_options(), first_job_id);
assert!(rejected.is_err());
let mut unavailable = ready_options();
unavailable.composition_ready = false;
let second_job_id = job_id();
let second_job_id = match second_job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
assert!(crate::map_backfill_request(request("latest_address"), &unavailable, second_job_id).is_err());
}
#[test]
fn request_preview_never_contains_address_or_signature_values() {
let job_id = job_id();
let job_id = match job_id {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
let mapped = crate::map_backfill_request(request("latest_address"), &ready_options(), job_id);
assert!(mapped.is_ok());
let mapped = match mapped {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let preview = crate::project_backfill_request(&mapped);
assert!(preview.is_ok());
let preview = match preview {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let serialized = serde_json::to_string(&preview);
assert!(serialized.is_ok());
if let std::result::Result::Ok(serialized) = serialized {
assert!(!serialized.contains("11111111111111111111111111111111"));
assert!(!serialized.contains(&"1".repeat(64)));
assert!(serialized.contains("mainnet-beta"));
assert!(serialized.contains("backfill_pool"));
}
}

View File

@@ -0,0 +1,31 @@
// file: crates/ksp-app-backfill-desk/unit_tests/dto_backfill.rs
// version: 1
#[test]
fn request_limits_are_derived_from_job_owned_public_bounds() {
let limits = crate::backfill_request_limits();
assert!(limits.is_ok());
let limits = match limits {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(usize::try_from(limits.max_page_size), std::result::Result::Ok(ksp_job_backfill_lib::MAX_BACKFILL_PAGE_SIZE));
assert_eq!(usize::try_from(limits.max_pages), std::result::Result::Ok(ksp_job_backfill_lib::MAX_BACKFILL_PAGES));
assert_eq!(usize::try_from(limits.max_candidates), std::result::Result::Ok(ksp_job_backfill_lib::MAX_BACKFILL_CANDIDATES));
assert_eq!(usize::try_from(limits.max_hydration_concurrency), std::result::Result::Ok(ksp_job_backfill_lib::MAX_BACKFILL_HYDRATION_CONCURRENCY));
assert_eq!(usize::try_from(limits.min_signature_text_bytes), std::result::Result::Ok(ksp_job_backfill_lib::MIN_BACKFILL_SIGNATURE_TEXT_BYTES));
assert_eq!(usize::try_from(limits.max_signature_text_bytes), std::result::Result::Ok(ksp_job_backfill_lib::MAX_BACKFILL_SIGNATURE_TEXT_BYTES));
assert!(limits.default_page_size <= limits.max_page_size);
assert!(limits.default_max_pages <= limits.max_pages);
assert!(limits.default_max_candidates <= limits.max_candidates);
assert!(limits.default_hydration_concurrency <= limits.max_hydration_concurrency);
}
#[test]
fn request_options_expose_exact_current_commitments_and_http_scopes() {
assert_eq!(crate::backfill_commitment_codes(), vec!["finalized".to_owned(), "confirmed".to_owned()]);
assert_eq!(
crate::backfill_scope_kind_codes(),
vec!["latest_address".to_owned(), "before_address".to_owned(), "after_address".to_owned(), "explicit_signatures".to_owned()]
);
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/unit_tests/dto_common.rs
// version: 4
// version: 5
#[test]
fn command_error_projection_excludes_arbitrary_context_and_source_values() {
@@ -15,11 +15,20 @@ fn command_error_projection_excludes_arbitrary_context_and_source_values() {
#[test]
fn transport_options_projection_contains_only_safe_transport_metadata() {
let limits = crate::backfill_request_limits();
assert!(limits.is_ok());
let limits = match limits {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let dto = crate::BackfillDeskOptionsDto {
commitments: crate::backfill_commitment_codes(),
http_routes: vec![crate::BackfillHttpRouteOptionDto { pooled: false, providers: vec!["solana-public".to_owned()], role: "default".to_owned() }],
limits,
composition_ready: true,
configured_networks: vec!["devnet".to_owned()],
network_coherent: true,
scope_kinds: crate::backfill_scope_kind_codes(),
store_diagnostic: std::option::Option::None,
store_network: std::option::Option::Some("devnet".to_owned()),
store_ready: true,