// 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; }