101 lines
4.3 KiB
Rust
101 lines
4.3 KiB
Rust
// file: crates/ksp-interface-lib/tests/security_hardening.rs
|
|
// version: 1
|
|
|
|
//! Adversarial and ownership-hardening canaries for passive Interface acquisition events.
|
|
|
|
const HOSTILE_MARKER: &str = "INTERFACE-ACQUISITION-SECRET-CANARY";
|
|
|
|
#[test]
|
|
fn v0_3_5_pre_005_signature_and_event_debug_never_render_signature_bytes() {
|
|
let mut bytes = [0x41_u8; 64];
|
|
bytes[..HOSTILE_MARKER.len()].copy_from_slice(HOSTILE_MARKER.as_bytes());
|
|
let signature = ksp_interface_lib::TransactionSignature::new(bytes);
|
|
assert_eq!(signature.as_bytes(), &bytes);
|
|
let signature_debug = std::format!("{signature:?}");
|
|
assert_eq!(signature_debug, "TransactionSignature(..)");
|
|
assert!(!signature_debug.contains(HOSTILE_MARKER));
|
|
let event = ksp_interface_lib::TransactionExecutionEvent::new(u64::MAX, signature, ksp_interface_lib::TransactionExecutionOutcome::Failed);
|
|
let event_debug = std::format!("{event:?}");
|
|
assert!(event_debug.contains("TransactionExecutionEvent"));
|
|
assert!(event_debug.contains("18446744073709551615"));
|
|
assert!(event_debug.contains("Failed"));
|
|
assert!(!event_debug.contains(HOSTILE_MARKER));
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn v0_3_5_pre_005_acquisition_structs_keep_exact_minimal_fields_without_payload_or_source_metadata() {
|
|
let lifecycle_source = include_str!("../src/slot_lifecycle.rs");
|
|
let execution_source = include_str!("../src/transaction_execution.rs");
|
|
assert!(lifecycle_source.contains("pub struct SlotLifecycleEvent {\n slot: u64,\n stage: SlotLifecycleStage,\n}"));
|
|
assert!(execution_source.contains("pub struct TransactionSignature([u8; 64]);"));
|
|
assert!(execution_source.contains(
|
|
"pub struct TransactionExecutionEvent {\n slot: u64,\n signature: TransactionSignature,\n outcome: TransactionExecutionOutcome,\n}"
|
|
));
|
|
for source in [lifecycle_source, execution_source] {
|
|
for forbidden in [
|
|
"std::vec::Vec<",
|
|
"std::string::String",
|
|
"Box<",
|
|
"serde_json::Value",
|
|
"timestamp:",
|
|
"provider_id:",
|
|
"endpoint:",
|
|
"filter:",
|
|
"network:",
|
|
"payload:",
|
|
] {
|
|
assert!(!source.contains(forbidden), "forbidden acquisition field/surface detected: {forbidden}");
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn v0_3_5_pre_005_interface_exports_no_second_raw_or_deferred_event_family() {
|
|
let crate_root = include_str!("../src/lib.rs");
|
|
for forbidden in [
|
|
"RawTransaction",
|
|
"RawAccount",
|
|
"RawPayload",
|
|
"RawPageCursor",
|
|
"RawRetention",
|
|
"RawObservation",
|
|
"TransactionLogEvent",
|
|
"TransactionCommitmentEvent",
|
|
"LedgerEntryEvent",
|
|
"VoteEvent",
|
|
"BlockEvent",
|
|
] {
|
|
assert!(!crate_root.contains(forbidden), "forbidden Interface export detected: {forbidden}");
|
|
}
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn v0_3_5_pre_005_program_instruction_foundation_remains_bounded_and_unchanged() {
|
|
assert_eq!(ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_ACCOUNTS, 255);
|
|
assert_eq!(ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_DATA_LEN, 10_240);
|
|
let program_id = ksp_interface_lib::Pubkey::new_from_array([0xD1_u8; 32]);
|
|
let account = ksp_interface_lib::ProgramAccountMeta::readonly(ksp_interface_lib::Pubkey::new_from_array([0xD2_u8; 32]), false);
|
|
let admitted = ksp_interface_lib::ProgramInstruction::try_new(
|
|
program_id,
|
|
std::vec![account; ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_ACCOUNTS],
|
|
std::vec![0x5A_u8; ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_DATA_LEN],
|
|
);
|
|
assert!(admitted.is_ok());
|
|
let admitted = match admitted {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
assert_eq!(admitted.accounts().len(), ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_ACCOUNTS);
|
|
assert_eq!(admitted.data().len(), ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_DATA_LEN);
|
|
let too_many_accounts =
|
|
ksp_interface_lib::ProgramInstruction::try_new(program_id, std::vec![account; ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_ACCOUNTS + 1], std::vec![]);
|
|
assert!(too_many_accounts.is_err());
|
|
let oversized_data =
|
|
ksp_interface_lib::ProgramInstruction::try_new(program_id, std::vec![], std::vec![0x5A_u8; ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_DATA_LEN + 1]);
|
|
assert!(oversized_data.is_err());
|
|
return;
|
|
}
|