// file: kb_materializer_lifecycle/src/materializer.rs // version: 13 //! Stable lifecycle projections derived from exact decoded observations. const ACCEPTED_FAMILIES: &[kb_model::EventFamily] = &[ kb_model::EventFamily::Lifecycle, kb_model::EventFamily::Admin, kb_model::EventFamily::Audit, ]; const ADDRESS_LOOKUP_TABLE_SURFACE: &str = "solana_native_address_lookup_table"; const ADDRESS_LOOKUP_TABLE_ENTRIES: &[&str] = &[ "create_lookup_table", "freeze_lookup_table", "extend_lookup_table", "deactivate_lookup_table", "close_lookup_table", ]; const BPF_LOADER_DEPRECATED_SURFACE: &str = "solana_native_bpf_loader_deprecated"; const BPF_LOADER_SURFACE: &str = "solana_native_bpf_loader"; const BPF_LOADER_UPGRADEABLE_SURFACE: &str = "solana_native_bpf_loader_upgradeable"; const LOADER_V4_SURFACE: &str = "solana_native_loader_v4"; const FEATURE_SURFACE: &str = "solana_native_feature"; const FEATURE_ENTRIES: &[&str] = &["revoke_pending_activation"]; const IMMUTABLE_LOADER_ENTRIES: &[&str] = &["finalize"]; const UPGRADEABLE_LOADER_ENTRIES: &[&str] = &[ "initialize_buffer", "deploy_with_max_data_len", "upgrade", "close", "extend_program", ]; const LOADER_V4_ENTRIES: &[&str] = &["set_program_length", "deploy", "retract", "finalize"]; const SLASHING_SURFACE: &str = "solana_native_slashing"; const SLASHING_ENTRIES: &[&str] = &["close_violation_report", "duplicate_block_proof"]; const SYSTEM_SURFACE: &str = "solana_native_system"; const SYSTEM_ACCOUNT_ENTRIES: &[&str] = &[ "create_account", "create_account_with_seed", "allocate", "allocate_with_seed", "create_account_allow_prefund", ]; const SYSTEM_NONCE_ENTRIES: &[&str] = &[ "advance_nonce_account", "withdraw_nonce_account", "initialize_nonce_account", "authorize_nonce_account", "upgrade_nonce_account", ]; const ZK_ELGAMAL_PROOF_SURFACE: &str = "solana_native_zk_elgamal_proof"; const ZK_ELGAMAL_CLOSE_ENTRIES: &[&str] = &["close_context_state"]; const ZK_ELGAMAL_VERIFY_ENTRIES: &[&str] = &[ "verify_zero_ciphertext", "verify_ciphertext_ciphertext_equality", "verify_ciphertext_commitment_equality", "verify_pubkey_validity", "verify_percentage_with_cap", "verify_batched_range_proof_u64", "verify_batched_range_proof_u128", "verify_batched_range_proof_u256", "verify_grouped_ciphertext_2_handles_validity", "verify_batched_grouped_ciphertext_2_handles_validity", "verify_grouped_ciphertext_3_handles_validity", "verify_batched_grouped_ciphertext_3_handles_validity", ]; #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum ProjectionKind { AddressLookupTable, FeatureGate, ProgramLoader(&'static str), SlashingViolationReportInitialization, SlashingViolationReportClosure, SystemAccountLifecycle, DurableNonceAccount, ZkProofContextInitialization, ZkProofContextClosure, } impl ProjectionKind { fn domain(self) -> &'static str { return match self { Self::AddressLookupTable => "address_lookup_table", Self::FeatureGate => "feature_gate", Self::ProgramLoader(_) => "program_loader", Self::SlashingViolationReportInitialization | Self::SlashingViolationReportClosure => { "slashing_violation_report" }, Self::SystemAccountLifecycle => "system_account", Self::DurableNonceAccount => "durable_nonce_account", Self::ZkProofContextInitialization | Self::ZkProofContextClosure => "zk_proof_context", }; } fn loader_surface(self) -> std::option::Option<&'static str> { return match self { Self::ProgramLoader(surface) => std::option::Option::Some(surface), _ => std::option::Option::None, }; } fn output_key(self, surface_code: &str, operation: &str) -> std::string::String { return match self { Self::AddressLookupTable => format!("address_lookup_table:{operation}:0"), Self::FeatureGate => format!("feature_gate:{operation}:0"), Self::ProgramLoader(_) => { format!("program_loader:{surface_code}:{operation}:0") }, Self::SlashingViolationReportInitialization | Self::SlashingViolationReportClosure => { format!("slashing_violation_report:{operation}:0") }, Self::SystemAccountLifecycle => format!("system_account:{operation}:0"), Self::DurableNonceAccount => format!("durable_nonce_account:{operation}:0"), Self::ZkProofContextInitialization | Self::ZkProofContextClosure => { format!("zk_proof_context:{operation}:0") }, }; } } /// Stable lifecycle materializer for supported native lifecycle projections. #[derive(Clone, Debug, Default)] pub struct LifecycleMaterializer; impl kb_materializer_api::Materializer for crate::LifecycleMaterializer { fn materializer_name(&self) -> &'static str { return "kb_materializer_lifecycle"; } fn materializer_version(&self) -> &'static str { return env!("CARGO_PKG_VERSION"); } fn accepts_event(&self, event: &kb_model::DecodedProtocolEvent) -> bool { return family_is_accepted(event.event_family) && static_projection(event.surface_code.0.as_str(), event.event_name.0.as_str()) .is_some(); } fn materialize_event( &self, event: &kb_model::DecodedProtocolEvent, ) -> kb_core::Result> { if !kb_materializer_api::Materializer::accepts_event(self, event) { return std::result::Result::Ok(std::vec::Vec::new()); } return std::result::Result::Ok(std::vec::Vec::new()); } } impl kb_materializer_api::EventMaterializer for crate::LifecycleMaterializer { fn identity(&self) -> kb_materializer_api::MaterializerIdentity { return kb_materializer_api::MaterializerIdentity { name: "solana_native_lifecycle".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } fn accepted_families(&self) -> &'static [kb_model::EventFamily] { return ACCEPTED_FAMILIES; } fn accepts_observation(&self, observation: &kb_decoder_api::DecodedObservation) -> bool { return family_is_accepted(observation.event.event_family) && observation_projection(observation).is_some(); } fn transaction_policy( &self, _family: kb_model::EventFamily, ) -> kb_materializer_api::MaterializationTransactionPolicy { return kb_materializer_api::MaterializationTransactionPolicy::SuccessfulCommittedOnly; } fn materialize( &self, observation: &kb_decoder_api::DecodedObservation, ) -> kb_materializer_api::MaterializerExecutionResult { let projection = match observation_projection(observation) { std::option::Option::Some(value) => value, std::option::Option::None => { tracing::debug!( target: crate::TRACING_TARGET, action = "materialize_lifecycle", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), accepted = false, "ignore observation outside supported native lifecycle projections" ); return kb_materializer_api::MaterializerExecutionResult::ignored(); }, }; if observation.transaction_failed || !observation.observation_committed { tracing::debug!( target: crate::TRACING_TARGET, action = "materialize_lifecycle", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), accepted = true, committed = observation.observation_committed, transaction_failed = observation.transaction_failed, "refuse uncommitted native lifecycle observation" ); return kb_materializer_api::MaterializerExecutionResult::refused( "failed_transaction_lifecycle_refused", "failed or uncommitted native lifecycle observations cannot create lifecycle outputs", ); } let accounts = observation .payload_json .get("accounts") .cloned() .unwrap_or(serde_json::Value::Null); let parameters = observation .payload_json .get("parameters") .cloned() .unwrap_or(serde_json::Value::Null); let operation = observation.event.event_name.0.clone(); let output_key = projection.output_key(observation.event.surface_code.0.as_str(), operation.as_str()); let domain = projection.domain(); let loader_surface = projection.loader_surface(); let projection_details = projection_details(projection, &accounts, ¶meters, operation.as_str()); tracing::debug!( target: crate::TRACING_TARGET, action = "materialize_lifecycle", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), projection_domain = domain, accepted = true, committed = true, output_count = 1_usize, "materialize committed native lifecycle observation" ); let output = kb_materializer_api::MaterializedOutput { output_key, family: kb_model::MaterializedEventFamily::Lifecycle, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "committed_instruction_lifecycle_event", "domain": domain, "loaderSurface": loader_surface, "operation": operation, "programId": observation.event.program_id.0.clone(), "signature": observation.event.signature.0.clone(), "slot": observation.event.slot.0, "instructionPath": observation.event.instruction_path.0.clone(), "transactionSucceeded": true, "accounts": accounts, "parameters": parameters, "projection": projection_details, }), }; return kb_materializer_api::MaterializerExecutionResult { status: kb_materializer_api::MaterializerOutcomeStatus::Inserted, outputs: std::vec![output], diagnostics: std::vec::Vec::new(), }; } } fn family_is_accepted(family: kb_model::EventFamily) -> bool { return ACCEPTED_FAMILIES.iter().any(|accepted| return *accepted == family); } fn observation_projection( observation: &kb_decoder_api::DecodedObservation, ) -> std::option::Option { let surface_code = observation.event.surface_code.0.as_str(); let entry_code = observation.event.event_name.0.as_str(); let static_projection = static_projection(surface_code, entry_code); if static_projection.is_some() { return static_projection; } if surface_code == ZK_ELGAMAL_PROOF_SURFACE && contains(ZK_ELGAMAL_VERIFY_ENTRIES, entry_code) && observation .payload_json .get("parameters") .and_then(|parameters| return parameters.get("contextStateRequested")) .and_then(serde_json::Value::as_bool) == std::option::Option::Some(true) { return std::option::Option::Some(ProjectionKind::ZkProofContextInitialization); } return std::option::Option::None; } fn static_projection(surface_code: &str, entry_code: &str) -> std::option::Option { if surface_code == FEATURE_SURFACE && contains(FEATURE_ENTRIES, entry_code) { return std::option::Option::Some(ProjectionKind::FeatureGate); } if surface_code == ADDRESS_LOOKUP_TABLE_SURFACE && contains(ADDRESS_LOOKUP_TABLE_ENTRIES, entry_code) { return std::option::Option::Some(ProjectionKind::AddressLookupTable); } if (surface_code == BPF_LOADER_DEPRECATED_SURFACE || surface_code == BPF_LOADER_SURFACE) && contains(IMMUTABLE_LOADER_ENTRIES, entry_code) { let loader_surface = if surface_code == BPF_LOADER_DEPRECATED_SURFACE { BPF_LOADER_DEPRECATED_SURFACE } else { BPF_LOADER_SURFACE }; return std::option::Option::Some(ProjectionKind::ProgramLoader(loader_surface)); } if surface_code == BPF_LOADER_UPGRADEABLE_SURFACE && contains(UPGRADEABLE_LOADER_ENTRIES, entry_code) { return std::option::Option::Some(ProjectionKind::ProgramLoader( BPF_LOADER_UPGRADEABLE_SURFACE, )); } if surface_code == LOADER_V4_SURFACE && contains(LOADER_V4_ENTRIES, entry_code) { return std::option::Option::Some(ProjectionKind::ProgramLoader(LOADER_V4_SURFACE)); } if surface_code == SLASHING_SURFACE && contains(SLASHING_ENTRIES, entry_code) { return if entry_code == "duplicate_block_proof" { std::option::Option::Some(ProjectionKind::SlashingViolationReportInitialization) } else { std::option::Option::Some(ProjectionKind::SlashingViolationReportClosure) }; } if surface_code == SYSTEM_SURFACE && contains(SYSTEM_ACCOUNT_ENTRIES, entry_code) { return std::option::Option::Some(ProjectionKind::SystemAccountLifecycle); } if surface_code == SYSTEM_SURFACE && contains(SYSTEM_NONCE_ENTRIES, entry_code) { return std::option::Option::Some(ProjectionKind::DurableNonceAccount); } if surface_code == ZK_ELGAMAL_PROOF_SURFACE && contains(ZK_ELGAMAL_CLOSE_ENTRIES, entry_code) { return std::option::Option::Some(ProjectionKind::ZkProofContextClosure); } return std::option::Option::None; } fn projection_details( projection: ProjectionKind, accounts: &serde_json::Value, parameters: &serde_json::Value, operation: &str, ) -> serde_json::Value { return match projection { ProjectionKind::SlashingViolationReportInitialization => { serde_json::json!({ "targetAccount": account_key_for_role(accounts, "violation_report"), "proofAccount": account_key_for_role(accounts, "proof_account"), "violationSlot": parameters.get("violationSlot").cloned().unwrap_or(serde_json::Value::Null), "nodePubkey": parameters.get("nodePubkey").cloned().unwrap_or(serde_json::Value::Null), "reporter": parameters.get("reporter").cloned().unwrap_or(serde_json::Value::Null), "lamportDestination": parameters.get("destination").cloned().unwrap_or(serde_json::Value::Null), "stateTransition": "pda_assigned_allocated_and_data_stored_after_successful_duplicate_block_proof_acceptance", "proofMaterialized": false, "penaltyAppliedByProgram": false, "enforcementSemantics": "violation_report_only_external_consensus_enforcement", }) }, ProjectionKind::SlashingViolationReportClosure => serde_json::json!({ "targetAccount": account_key_for_role(accounts, "violation_report"), "lamportDestination": account_key_for_role(accounts, "destination"), "stateTransition": "closed_after_minimum_retention_lamports_reclaimed_owner_reset_to_system_program", "minimumRetentionEpochs": 3, "transactionFinalAccountStateCaptured": false, }), ProjectionKind::SystemAccountLifecycle => serde_json::json!({ "targetAccount": first_account_key_for_roles( accounts, &["new_account", "allocated_account", "derived_account"], ), "fundingAccount": account_key_for_role(accounts, "funding_account"), "baseAccount": account_key_for_role(accounts, "base_account"), "requestedLamports": parameters.get("lamports").cloned().unwrap_or(serde_json::Value::Null), "requestedSpace": parameters.get("space").cloned().unwrap_or(serde_json::Value::Null), "requestedOwner": parameters.get("owner").cloned().unwrap_or(serde_json::Value::Null), "seed": parameters.get("seed").cloned().unwrap_or(serde_json::Value::Null), "stateTransition": system_account_transition(operation), "lamportTransferRepresentedByCoreBalanceChanges": operation == "create_account" || operation == "create_account_with_seed" || operation == "create_account_allow_prefund", "transactionFinalAccountStateCaptured": false, }), ProjectionKind::DurableNonceAccount => serde_json::json!({ "targetAccount": account_key_for_role(accounts, "nonce_account"), "authorityAccount": account_key_for_role(accounts, "nonce_authority"), "lamportDestination": account_key_for_role(accounts, "recipient_account"), "stateTransition": nonce_transition(operation), "newAuthority": parameters.get("authority").cloned().unwrap_or(serde_json::Value::Null), "withdrawLamports": parameters.get("lamports").cloned().unwrap_or(serde_json::Value::Null), "closureSemantics": if operation == "withdraw_nonce_account" { serde_json::Value::String("closes_when_entire_balance_is_withdrawn".to_string()) } else { serde_json::Value::Null }, "transactionFinalAccountStateCaptured": false, }), ProjectionKind::ZkProofContextInitialization => serde_json::json!({ "targetAccount": account_key_for_role(accounts, "proof_context_state"), "contextStateAuthority": account_key_for_role(accounts, "context_state_authority"), "proofType": parameters.get("proofType").cloned().unwrap_or(serde_json::Value::Null), "stateTransition": "initialized_after_successful_runtime_verification", "proofMaterialized": false, }), ProjectionKind::ZkProofContextClosure => serde_json::json!({ "targetAccount": account_key_for_role(accounts, "proof_context_state"), "lamportDestination": account_key_for_role(accounts, "lamport_destination"), "contextStateAuthority": account_key_for_role(accounts, "context_state_authority"), "stateTransition": "closed_lamports_reclaimed_owner_reset_to_system_program", "proofMaterialized": false, }), ProjectionKind::AddressLookupTable | ProjectionKind::FeatureGate | ProjectionKind::ProgramLoader(_) => serde_json::json!({ "stateTransition": operation, }), }; } fn system_account_transition(operation: &str) -> &'static str { return match operation { "create_account" => "created_allocated_funded_and_assigned", "create_account_with_seed" => "derived_account_created_allocated_funded_and_assigned", "create_account_allow_prefund" => "prefunded_account_initialized_allocated_and_assigned", "allocate" => "account_data_space_allocated", "allocate_with_seed" => "derived_account_data_space_allocated", _ => "unknown", }; } fn nonce_transition(operation: &str) -> &'static str { return match operation { "initialize_nonce_account" => "initialized", "advance_nonce_account" => "nonce_advanced", "authorize_nonce_account" => "authority_changed", "upgrade_nonce_account" => "legacy_version_upgraded", "withdraw_nonce_account" => "lamports_withdrawn_possible_closure", _ => "unknown", }; } fn first_account_key_for_roles(accounts: &serde_json::Value, roles: &[&str]) -> serde_json::Value { for role in roles { let value = account_key_for_role(accounts, role); if !value.is_null() { return value; } } return serde_json::Value::Null; } fn account_key_for_role(accounts: &serde_json::Value, role: &str) -> serde_json::Value { let account_key = accounts.as_array().and_then(|values| { return values.iter().find_map(|value| { if value.get("role").and_then(serde_json::Value::as_str) != std::option::Option::Some(role) { return std::option::Option::None; } return value .get("accountKey") .and_then(serde_json::Value::as_str) .map(|account_key| return account_key.to_string()); }); }); return match account_key { std::option::Option::Some(value) => serde_json::Value::String(value), std::option::Option::None => serde_json::Value::Null, }; } fn contains(entries: &[&str], entry_code: &str) -> bool { return entries.iter().any(|entry| return *entry == entry_code); } #[cfg(test)] mod tests { fn observation_with_payload( surface_code: &str, entry_code: &str, event_family: kb_model::EventFamily, transaction_failed: bool, accounts: serde_json::Value, parameters: serde_json::Value, ) -> kb_decoder_api::DecodedObservation { return kb_decoder_api::DecodedObservation { event_key: format!("{entry_code}:0"), event: kb_model::DecodedProtocolEvent { signature: kb_model::Signature("signature".to_string()), slot: kb_model::Slot(42), instruction_path: kb_model::InstructionPath("0".to_string()), program_id: kb_model::ProgramId("program-id".to_string()), protocol_code: kb_model::ProtocolCode("solana_native".to_string()), surface_code: kb_model::SurfaceCode(surface_code.to_string()), event_code: kb_model::EventCode(format!("{surface_code}.{entry_code}")), event_name: kb_model::EventName(entry_code.to_string()), event_family, source_kind: kb_model::EventSourceKind::Instruction, confidence: kb_model::DecoderConfidence::ManualExact, }, payload_json: serde_json::json!({ "accounts": accounts, "parameters": parameters, }), transaction_failed, transaction_error: if transaction_failed { std::option::Option::Some(serde_json::json!({"InstructionError": [0, "Custom"]})) } else { std::option::Option::None }, observation_committed: !transaction_failed, proof: kb_decoder_api::DecoderProof { kind: kb_decoder_api::DecoderProofKind::Manual, confidence: kb_model::DecoderConfidence::ManualExact, evidence: std::vec!["fixture".to_string()], }, }; } fn observation( surface_code: &str, entry_code: &str, transaction_failed: bool, ) -> kb_decoder_api::DecodedObservation { return observation_with_payload( surface_code, entry_code, kb_model::EventFamily::Lifecycle, transaction_failed, serde_json::json!([{"role": "target", "accountKey": "account"}]), serde_json::json!({"value": 41}), ); } fn nonce_observation( entry_code: &str, family: kb_model::EventFamily, transaction_failed: bool, ) -> kb_decoder_api::DecodedObservation { return observation_with_payload( super::SYSTEM_SURFACE, entry_code, family, transaction_failed, serde_json::json!([ {"role": "nonce_account", "accountKey": "nonce111"}, {"role": "recipient_account", "accountKey": "recipient111"}, {"role": "nonce_authority", "accountKey": "authority111"} ]), serde_json::json!({ "authority": "new-authority111", "lamports": 55, }), ); } fn slashing_observation( entry_code: &str, transaction_failed: bool, ) -> kb_decoder_api::DecodedObservation { let (family, accounts) = if entry_code == "duplicate_block_proof" { ( kb_model::EventFamily::Audit, serde_json::json!([ {"role": "proof_account", "accountKey": "proof111"}, {"role": "violation_report", "accountKey": "report111"}, {"role": "instructions_sysvar", "accountKey": kb_program_ids::SYSVAR_INSTRUCTIONS_PROGRAM_ID}, {"role": "system_program", "accountKey": kb_program_ids::SYSTEM_PROGRAM_ID} ]), ) } else { ( kb_model::EventFamily::Lifecycle, serde_json::json!([ {"role": "violation_report", "accountKey": "report111"}, {"role": "destination", "accountKey": "destination111"} ]), ) }; return observation_with_payload( super::SLASHING_SURFACE, entry_code, family, transaction_failed, accounts, serde_json::json!({ "proofType": "duplicate_block", "violationSlot": 42, "nodePubkey": "node111", "reporter": "reporter111", "destination": "destination111", "penaltyAppliedByProgram": false, }), ); } fn zk_observation( entry_code: &str, context_state_requested: bool, transaction_failed: bool, ) -> kb_decoder_api::DecodedObservation { let accounts = if entry_code == "close_context_state" { serde_json::json!([ {"role": "proof_context_state", "accountKey": "context111"}, {"role": "lamport_destination", "accountKey": "destination111"}, {"role": "context_state_authority", "accountKey": "authority111"} ]) } else if context_state_requested { serde_json::json!([ {"role": "proof_context_state", "accountKey": "context111"}, {"role": "context_state_authority", "accountKey": "authority111"} ]) } else { serde_json::json!([]) }; let family = if entry_code == "close_context_state" { kb_model::EventFamily::Lifecycle } else { kb_model::EventFamily::Audit }; return observation_with_payload( super::ZK_ELGAMAL_PROOF_SURFACE, entry_code, family, transaction_failed, accounts, serde_json::json!({ "proofType": entry_code, "contextStateRequested": context_state_requested, }), ); } #[test] fn successful_alt_lifecycle_creates_one_stable_output() { let materializer = crate::LifecycleMaterializer; let result = kb_materializer_api::EventMaterializer::materialize( &materializer, &observation(super::ADDRESS_LOOKUP_TABLE_SURFACE, "create_lookup_table", false), ); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs.len(), 1); assert_eq!(result.outputs[0].output_key, "address_lookup_table:create_lookup_table:0"); assert_eq!(result.outputs[0].payload_json["domain"], "address_lookup_table"); assert_eq!(result.outputs[0].payload_json["loaderSurface"], serde_json::Value::Null); } #[test] fn successful_loader_lifecycle_creates_program_projection() { let materializer = crate::LifecycleMaterializer; let result = kb_materializer_api::EventMaterializer::materialize( &materializer, &observation(super::BPF_LOADER_UPGRADEABLE_SURFACE, "deploy_with_max_data_len", false), ); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!( result.outputs[0].output_key, "program_loader:solana_native_bpf_loader_upgradeable:deploy_with_max_data_len:0" ); assert_eq!(result.outputs[0].payload_json["domain"], "program_loader"); assert_eq!( result.outputs[0].payload_json["loaderSurface"], super::BPF_LOADER_UPGRADEABLE_SURFACE ); } #[test] fn successful_feature_revoke_creates_feature_gate_projection() { let materializer = crate::LifecycleMaterializer; let result = kb_materializer_api::EventMaterializer::materialize( &materializer, &observation(super::FEATURE_SURFACE, "revoke_pending_activation", false), ); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].output_key, "feature_gate:revoke_pending_activation:0"); assert_eq!(result.outputs[0].payload_json["domain"], "feature_gate"); } #[test] fn every_committed_system_account_operation_creates_a_lifecycle_projection() { let materializer = crate::LifecycleMaterializer; for (operation, role, transition) in [ ("create_account", "new_account", "created_allocated_funded_and_assigned"), ( "create_account_with_seed", "new_account", "derived_account_created_allocated_funded_and_assigned", ), ("allocate", "allocated_account", "account_data_space_allocated"), ("allocate_with_seed", "derived_account", "derived_account_data_space_allocated"), ( "create_account_allow_prefund", "new_account", "prefunded_account_initialized_allocated_and_assigned", ), ] { let observation = observation_with_payload( super::SYSTEM_SURFACE, operation, kb_model::EventFamily::Lifecycle, false, serde_json::json!([ {"role": role, "accountKey": "target111"}, {"role": "funding_account", "accountKey": "funding111"}, {"role": "base_account", "accountKey": "base111"}, ]), serde_json::json!({ "lamports": 55, "space": 64, "owner": "owner111", "seed": "seed", }), ); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].output_key, format!("system_account:{operation}:0")); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "target111"); assert_eq!(result.outputs[0].payload_json["projection"]["stateTransition"], transition); } } #[test] fn system_account_creation_does_not_duplicate_balance_changes() { let materializer = crate::LifecycleMaterializer; let observation = observation_with_payload( super::SYSTEM_SURFACE, "create_account", kb_model::EventFamily::Lifecycle, false, serde_json::json!([ {"role": "funding_account", "accountKey": "funding111"}, {"role": "new_account", "accountKey": "target111"}, ]), serde_json::json!({"lamports": 55, "space": 64, "owner": "owner111"}), ); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.outputs[0].payload_json["projection"]["requestedLamports"], 55); assert_eq!( result.outputs[0].payload_json["projection"]["lamportTransferRepresentedByCoreBalanceChanges"], true ); assert!(result.outputs[0].payload_json["projection"].get("balanceChanges").is_none()); } #[test] fn every_committed_system_nonce_operation_creates_a_lifecycle_projection() { let materializer = crate::LifecycleMaterializer; for (entry_code, family, transition) in [ ("initialize_nonce_account", kb_model::EventFamily::Lifecycle, "initialized"), ("advance_nonce_account", kb_model::EventFamily::Lifecycle, "nonce_advanced"), ("authorize_nonce_account", kb_model::EventFamily::Admin, "authority_changed"), ( "upgrade_nonce_account", kb_model::EventFamily::Lifecycle, "legacy_version_upgraded", ), ( "withdraw_nonce_account", kb_model::EventFamily::Lifecycle, "lamports_withdrawn_possible_closure", ), ] { let observation = nonce_observation(entry_code, family, false); assert!(kb_materializer_api::EventMaterializer::accepts_observation( &materializer, &observation, )); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].payload_json["domain"], "durable_nonce_account"); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "nonce111"); assert_eq!( result.outputs[0].payload_json["projection"]["authorityAccount"], "authority111" ); assert_eq!(result.outputs[0].payload_json["projection"]["stateTransition"], transition); } } #[test] fn nonce_withdrawal_preserves_conditional_closure_semantics() { let materializer = crate::LifecycleMaterializer; let observation = nonce_observation("withdraw_nonce_account", kb_model::EventFamily::Lifecycle, false); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.outputs[0].payload_json["projection"]["withdrawLamports"], 55); assert_eq!( result.outputs[0].payload_json["projection"]["lamportDestination"], "recipient111" ); assert_eq!( result.outputs[0].payload_json["projection"]["closureSemantics"], "closes_when_entire_balance_is_withdrawn" ); assert_eq!( result.outputs[0].payload_json["projection"]["transactionFinalAccountStateCaptured"] .as_bool(), std::option::Option::Some(false) ); } #[test] fn zk_context_is_materialized_only_when_requested() { let materializer = crate::LifecycleMaterializer; let without_context = zk_observation("verify_zero_ciphertext", false, false); assert!(!kb_materializer_api::EventMaterializer::accepts_observation( &materializer, &without_context, )); let with_context = zk_observation("verify_zero_ciphertext", true, false); assert!(kb_materializer_api::EventMaterializer::accepts_observation( &materializer, &with_context, )); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &with_context); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].payload_json["domain"], "zk_proof_context"); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "context111"); assert_eq!( result.outputs[0].payload_json["projection"]["stateTransition"], "initialized_after_successful_runtime_verification" ); assert_eq!( result.outputs[0].payload_json["projection"]["proofMaterialized"].as_bool(), std::option::Option::Some(false) ); } #[test] fn zk_context_close_creates_a_stable_lifecycle_projection() { let materializer = crate::LifecycleMaterializer; let observation = zk_observation("close_context_state", false, false); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].output_key, "zk_proof_context:close_context_state:0"); assert_eq!( result.outputs[0].payload_json["projection"]["lamportDestination"], "destination111" ); assert_eq!( result.outputs[0].payload_json["projection"]["stateTransition"], "closed_lamports_reclaimed_owner_reset_to_system_program" ); } #[test] fn successful_slashing_proof_initializes_violation_report_projection() { let materializer = crate::LifecycleMaterializer; let observation = slashing_observation("duplicate_block_proof", false); assert!(kb_materializer_api::EventMaterializer::accepts_observation( &materializer, &observation, )); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!( result.outputs[0].output_key, "slashing_violation_report:duplicate_block_proof:0" ); assert_eq!(result.outputs[0].payload_json["domain"], "slashing_violation_report"); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "report111"); assert_eq!(result.outputs[0].payload_json["projection"]["proofMaterialized"], false); assert_eq!(result.outputs[0].payload_json["projection"]["penaltyAppliedByProgram"], false); } #[test] fn successful_slashing_close_creates_stable_closure_projection() { let materializer = crate::LifecycleMaterializer; let observation = slashing_observation("close_violation_report", false); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Inserted); assert_eq!( result.outputs[0].payload_json["projection"]["stateTransition"], "closed_after_minimum_retention_lamports_reclaimed_owner_reset_to_system_program" ); assert_eq!(result.outputs[0].payload_json["projection"]["minimumRetentionEpochs"], 3); assert_eq!( result.outputs[0].payload_json["projection"]["lamportDestination"], "destination111" ); } #[test] fn historical_zk_token_proof_is_not_materialized() { let materializer = crate::LifecycleMaterializer; let observation = observation_with_payload( "solana_native_zk_token_proof", "close_context_state", kb_model::EventFamily::Audit, false, serde_json::json!([]), serde_json::json!({}), ); assert!(!kb_materializer_api::EventMaterializer::accepts_observation( &materializer, &observation, )); let result = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Ignored); } #[test] fn loader_write_and_admin_events_are_not_lifecycle_projections() { let materializer = crate::LifecycleMaterializer; for entry_code in ["write", "set_authority", "transfer_authority"] { let observation = observation(super::BPF_LOADER_UPGRADEABLE_SURFACE, entry_code, false); assert!(!kb_materializer_api::EventMaterializer::accepts_observation( &materializer, &observation, )); } } #[test] fn unrelated_lifecycle_is_ignored() { let materializer = crate::LifecycleMaterializer; let result = kb_materializer_api::EventMaterializer::materialize( &materializer, &observation(super::SYSTEM_SURFACE, "transfer", false), ); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Ignored); } #[test] fn ata_lifecycle_is_owned_by_token_accounts_materializer_only() { let mut observation = observation("spl_associated_token_account", "create", false); observation.event.program_id = kb_model::ProgramId(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string()); assert!(!kb_materializer_api::EventMaterializer::accepts_observation( &crate::LifecycleMaterializer, &observation, )); let result = kb_materializer_api::EventMaterializer::materialize( &crate::LifecycleMaterializer, &observation, ); assert_eq!(result.status, kb_materializer_api::MaterializerOutcomeStatus::Ignored); assert!(result.outputs.is_empty()); } #[test] fn failed_native_lifecycle_is_refused() { let materializer = crate::LifecycleMaterializer; let observations = [ observation(super::ADDRESS_LOOKUP_TABLE_SURFACE, "close_lookup_table", true), observation(super::LOADER_V4_SURFACE, "deploy", true), nonce_observation("authorize_nonce_account", kb_model::EventFamily::Admin, true), zk_observation("verify_zero_ciphertext", true, true), slashing_observation("duplicate_block_proof", true), ]; for observation in observations { let policy = kb_materializer_api::validate_materialization_policy(&materializer, &observation); assert!(policy.is_err()); let direct = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); assert_eq!(direct.status, kb_materializer_api::MaterializerOutcomeStatus::Refused); } } #[test] fn output_serialization_is_deterministic() { let materializer = crate::LifecycleMaterializer; let observation = zk_observation("verify_batched_range_proof_u64", true, false); let first = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); let second = kb_materializer_api::EventMaterializer::materialize(&materializer, &observation); let first_json = match serde_json::to_string(&first) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { panic!("first lifecycle serialization failed: {error}") }, }; let second_json = match serde_json::to_string(&second) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { panic!("second lifecycle serialization failed: {error}") }, }; assert_eq!(first_json, second_json); } }