// file: kb-pipeline-demo-scenarios/src/metadata_solana_program_devnet_execution.rs // version: 1 //! Real Devnet simulation and controlled submission for Solana Program Metadata. /// Complete request for one Solana Program Metadata Devnet execution. #[derive(Clone, Debug, PartialEq)] pub struct DevnetSolanaProgramMetadataExecutionRequest { /// Stable caller-provided execution identifier. pub intent_id: std::string::String, /// Endpoint role used for reads, balance, blockhash and fee queries. pub query_role: std::string::String, /// Endpoint role used for simulation, submission and confirmation. pub transaction_role: std::string::String, /// Exact stable Solana Program Metadata operation. pub operation: kb_lib::ExMetadataSpmOperation, /// Bounded state reads required before execution. pub preflight_reads: std::vec::Vec, /// Explicit rent observations required by allocation and growth operations. pub rent_observations: std::vec::Vec, /// Bounded state reads repeated after confirmed submission. pub postcondition_reads: std::vec::Vec, /// Explicit approval for overwrite, destructive or irreversible operations. pub allow_destructive_operation: bool, /// Explicitly authorizes signing and submission after successful simulation. pub submit: bool, /// Explicit operator confirmation required for submission. pub operator_confirmed: bool, /// Materializes confirmed account snapshots after submission. pub materialize_after_confirmation: bool, } impl crate::DevnetSolanaProgramMetadataExecutionRequest { /// Creates a conservative simulation-only request. pub fn new( intent_id: impl std::convert::Into, operation: kb_lib::ExMetadataSpmOperation, ) -> Self { return Self { intent_id: intent_id.into(), query_role: "http_queries".to_string(), transaction_role: "http_transactions".to_string(), operation, preflight_reads: std::vec::Vec::new(), rent_observations: std::vec::Vec::new(), postcondition_reads: std::vec::Vec::new(), allow_destructive_operation: false, submit: false, operator_confirmed: false, materialize_after_confirmation: false, }; } /// Creates one conservative request from serialized typed operation JSON. pub fn from_operation_json( intent_id: impl std::convert::Into, operation_json: &str, ) -> kb_core::Result { if operation_json.contains('<') || operation_json.trim() == "..." { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata operation JSON still contains a placeholder", )); } let operation = match serde_json::from_str::(operation_json) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { return std::result::Result::Err(kb_core::Error::config(format!( "invalid typed Solana Program Metadata operation JSON: {error}" ))); }, }; return std::result::Result::Ok(Self::new(intent_id, operation)); } /// Validates request-local bounds independently from one profile. pub fn validate(&self) -> kb_core::Result<()> { if self.intent_id.trim().is_empty() { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata Devnet intent id must not be empty", )); } if self.query_role.trim().is_empty() || self.transaction_role.trim().is_empty() { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata endpoint roles must not be empty", )); } if self.preflight_reads.is_empty() || self.preflight_reads.len() > kb_pipeline::MAX_SOLANA_PROGRAM_METADATA_PREFLIGHT_ACCOUNTS || self.postcondition_reads.len() > kb_pipeline::MAX_SOLANA_PROGRAM_METADATA_PREFLIGHT_ACCOUNTS { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata stateful read inventory is empty or above the compiled bound", )); } if self.operation.requires_explicit_approval() && !self.allow_destructive_operation { return std::result::Result::Err(kb_core::Error::new( "execution_metadata_spm_destructive_approval_required", "destructive Solana Program Metadata execution requires explicit approval", )); } if self.submit && self.postcondition_reads.is_empty() { return std::result::Result::Err(kb_core::Error::config( "submitted Solana Program Metadata execution requires postcondition reads", )); } if self.materialize_after_confirmation && self.postcondition_reads.is_empty() { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata materialization requires postcondition reads", )); } return std::result::Result::Ok(()); } } /// Complete evidence produced by one Solana Program Metadata Devnet execution. #[derive(Clone, Debug, PartialEq)] pub struct DevnetSolanaProgramMetadataExecutionSummary { /// Profile used by the orchestration. pub profile_name: std::string::String, /// Exact classified cluster. pub cluster: kb_lib::ExApiExecutionCluster, /// Genesis hash returned by the selected endpoint. pub genesis_hash: std::string::String, /// Non-secret persistent wallet description. pub wallet: kb_wallet::WalletSummary, /// Wallet balance observed before planning. pub balance_lamports: u64, /// Stateful snapshots observed before simulation. pub before: std::vec::Vec, /// Stateful preflight report bound to the exact plan. pub stateful_preflight: kb_pipeline::SolanaProgramMetadataPreflightReport, /// Exact prepared plan. pub plan: kb_lib::ExApiPreparedExecutionPlan, /// Recent blockhash used by the exact transaction. pub latest_blockhash: kb_onchain_transport::LatestBlockhashResult, /// Fee estimate for the exact compiled message. pub fee: kb_onchain_transport::FeeForMessageResult, /// Exact real RPC simulation result. pub simulation: kb_lib::ExApiExecutionSimulationResult, /// Readiness report proving exact-message simulation and signer resolution. pub readiness: kb_pipeline::SolanaProgramMetadataExecutionReadinessReport, /// Submission result when explicitly authorized. pub send_result: std::option::Option, /// Confirmation result when submitted. pub confirmation: std::option::Option, /// Stateful snapshots observed after confirmed submission. pub after: std::vec::Vec, /// Stateful postcondition report after confirmed submission. pub post_execution: std::option::Option, /// Canonical projections emitted from confirmed account snapshots. pub materialized_snapshots: std::vec::Vec, } struct PreparedSolanaProgramMetadataExecution { wallet: kb_wallet::TemporaryWallet, unsigned: kb_lib::ExSolanaUnsignedTransaction, evidence: kb_lib::ExSolanaSimulationEvidence, summary: crate::DevnetSolanaProgramMetadataExecutionSummary, } /// Simulates one stable Solana Program Metadata operation against Devnet. pub async fn simulate_devnet_solana_program_metadata( http_pool: &kb_onchain_transport::HttpEndpointPool, profile: &kb_config::ProfileConfig, workspace_root: &std::path::Path, request: &crate::DevnetSolanaProgramMetadataExecutionRequest, observer: &O, ) -> kb_core::Result where O: crate::SolanaExecutionObserver, { if request.submit { return std::result::Result::Err(kb_core::Error::config( "simulate_devnet_solana_program_metadata requires submit=false", )); } let prepared = match prepare_execution(http_pool, profile, workspace_root, request, observer).await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; return std::result::Result::Ok(prepared.summary); } /// Executes one Solana Program Metadata simulation or authorized submission. pub async fn execute_devnet_solana_program_metadata( http_pool: &kb_onchain_transport::HttpEndpointPool, profile: &kb_config::ProfileConfig, workspace_root: &std::path::Path, request: &crate::DevnetSolanaProgramMetadataExecutionRequest, observer: &O, ) -> kb_core::Result where O: crate::SolanaExecutionObserver, { let prepared = match prepare_execution(http_pool, profile, workspace_root, request, observer).await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if !request.submit { return std::result::Result::Ok(prepared.summary); } if !prepared.summary.simulation.success { return std::result::Result::Err(kb_core::Error::new( "execution_simulation_failed", crate::simulation_failure_message(&prepared.summary.simulation), )); } if let std::result::Result::Err(error) = validate_profile_wallet_signers( prepared.unsigned.required_signer_pubkeys(), prepared.summary.wallet.public_key.as_str(), ) { return std::result::Result::Err(error); } let send_evaluation = match kb_lib::ExSafetyChecker .evaluate_send(&prepared.summary.plan, &prepared.summary.simulation) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if send_evaluation.decision == kb_lib::ExSafetyDecision::Deny { return std::result::Result::Err(kb_core::Error::new( "execution_send_denied", crate::violation_message(send_evaluation.violations.as_slice()), )); } let signed = match prepared .unsigned .sign_after_simulation(&prepared.evidence, &[prepared.wallet.as_signer()]) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if let std::result::Result::Err(error) = signed.verify_signatures() { return std::result::Result::Err(error); } let signature = signed.primary_signature().clone(); let mut summary = prepared.summary; let send_config = match kb_onchain_transport::SendTransactionConfig::from_execution_config( &profile.execution, std::option::Option::Some(summary.latest_blockhash.context.slot), ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let sent = match http_pool .send_transaction_for_role( request.transaction_role.as_str(), signed.transaction_base64().as_str(), &signature, &send_config, ) .await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; summary.send_result = std::option::Option::Some(sent.to_execution_result(kb_lib::ExApiExecutionCluster::Devnet)); let confirmation_config = match kb_onchain_transport::ConfirmTransactionConfig::from_execution_config( &profile.execution, std::option::Option::Some(summary.latest_blockhash.last_valid_block_height), std::option::Option::Some(summary.latest_blockhash.context.slot), ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let confirmation = match http_pool .confirm_transaction_for_roles( request.transaction_role.as_str(), request.query_role.as_str(), kb_lib::ExApiExecutionCluster::Devnet, &signature, &confirmation_config, ) .await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let confirmed = matches!( confirmation.status, kb_lib::ExApiExecutionConfirmationStatus::Confirmed | kb_lib::ExApiExecutionConfirmationStatus::Finalized ); summary.confirmation = std::option::Option::Some(confirmation); if confirmed { summary.after = match read_snapshots(http_pool, &request.postcondition_reads).await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let report = match kb_pipeline::inspect_solana_program_metadata_post_execution( &kb_pipeline::SolanaProgramMetadataPostExecutionRequest { operation: request.operation.clone(), before: summary.before.clone(), after: summary.after.clone(), }, ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if report.status == kb_pipeline::SolanaProgramMetadataPostconditionStatus::Contradicted { return std::result::Result::Err(kb_core::Error::new( "execution_metadata_spm_postcondition_contradicted", "confirmed Solana Program Metadata transaction contradicted its stateful postcondition", )); } summary.post_execution = std::option::Option::Some(report); if request.materialize_after_confirmation { summary.materialized_snapshots = materialize_confirmed_snapshots(summary.after.as_slice()); } } return std::result::Result::Ok(summary); } async fn prepare_execution( http_pool: &kb_onchain_transport::HttpEndpointPool, profile: &kb_config::ProfileConfig, workspace_root: &std::path::Path, request: &crate::DevnetSolanaProgramMetadataExecutionRequest, observer: &O, ) -> kb_core::Result where O: crate::SolanaExecutionObserver, { if let std::result::Result::Err(error) = request.validate() { return std::result::Result::Err(error); } if let std::result::Result::Err(error) = validate_profile(profile, request) { return std::result::Result::Err(error); } if let std::result::Result::Err(error) = crate::ensure_not_cancelled(observer, "solana_program_metadata_validate") { return std::result::Result::Err(error); } let genesis = match http_pool.get_genesis_hash_for_role(request.query_role.as_str()).await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if genesis.classified_cluster != std::option::Option::Some(kb_lib::ExApiExecutionCluster::Devnet) { return std::result::Result::Err(kb_core::Error::new( "execution_cluster_mismatch", format!( "expected Devnet genesis hash but endpoint returned {} classified as {:?}", genesis.genesis_hash, genesis.classified_cluster ), )); } let wallet = match crate::load_profile_wallet(profile, workspace_root).await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let wallet_summary = wallet.summary(); let fee_payer = kb_lib::MdPubkey(wallet_summary.public_key.clone()); let balance = match http_pool .get_balance_for_role( request.query_role.as_str(), &fee_payer, &kb_onchain_transport::GetBalanceConfig::confirmed(), ) .await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if balance.lamports < profile.execution.max_fee_lamports { return std::result::Result::Err(kb_core::Error::new( "execution_balance_insufficient", "Devnet wallet balance is below the configured fee ceiling", )); } let intent = build_intent(profile, request, fee_payer.clone()); let plan = match kb_lib::ExApiTypedInstructionExecutor::build_prepared_plan( &kb_lib::ExMetadataSolanaProgramMetadataExecutor, &intent, ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let plan_evaluation = match kb_lib::ExSafetyChecker.evaluate_prepared_plan(&plan) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if plan_evaluation.decision == kb_lib::ExSafetyDecision::Deny { return std::result::Result::Err(kb_core::Error::new( "execution_metadata_spm_plan_denied", crate::violation_message(plan_evaluation.violations.as_slice()), )); } let before = match read_snapshots(http_pool, &request.preflight_reads).await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let stateful_preflight = match kb_pipeline::inspect_solana_program_metadata_preflight( &kb_pipeline::SolanaProgramMetadataPreflightRequest { intent: intent.clone(), plan: plan.clone(), before: before.clone(), rent_observations: request.rent_observations.clone(), }, ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let latest_blockhash = match http_pool .get_latest_blockhash_for_role( request.query_role.as_str(), &kb_onchain_transport::GetLatestBlockhashConfig::confirmed(), ) .await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let unsigned = match kb_lib::executor_solana_build_legacy_transaction( &plan, latest_blockhash.blockhash.as_str(), ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if let std::result::Result::Err(error) = validate_profile_wallet_signers( unsigned.required_signer_pubkeys(), wallet_summary.public_key.as_str(), ) { return std::result::Result::Err(error); } let fee = match http_pool .get_fee_for_message_for_role( request.query_role.as_str(), unsigned.message_base64().as_str(), &kb_onchain_transport::GetFeeForMessageConfig::new( kb_onchain_transport::RpcCommitmentLevel::Confirmed, std::option::Option::Some(latest_blockhash.context.slot), ), ) .await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let unsigned_base64 = match unsigned.transaction_base64() { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let simulation_config = match kb_onchain_transport::SimulateTransactionConfig::new( kb_onchain_transport::RpcCommitmentLevel::Confirmed, false, false, std::option::Option::Some(latest_blockhash.context.slot), true, std::option::Option::None, ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; crate::emit( observer, crate::SolanaExecutionProgressLevel::Info, "solana_program_metadata_simulation", format!("simulating exact Solana Program Metadata message {}", unsigned.message_hash()), std::option::Option::None, ); let simulation_rpc = match http_pool .simulate_transaction_for_role( request.transaction_role.as_str(), unsigned_base64.as_str(), &simulation_config, ) .await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let simulation = simulation_rpc.to_execution_result( kb_lib::ExApiExecutionCluster::Devnet, kb_lib::ExApiExecutionBlockhashKind::Latest, std::option::Option::Some( simulation_rpc.context.slot.saturating_sub(latest_blockhash.context.slot), ), std::option::Option::None, std::option::Option::None, std::option::Option::Some(&fee), ); let readiness = match kb_pipeline::validate_solana_program_metadata_execution_readiness( &kb_pipeline::SolanaProgramMetadataExecutionReadinessRequest { plan: plan.clone(), preflight: stateful_preflight.clone(), message_hash: unsigned.message_hash().to_string(), simulated_message_hash: unsigned.message_hash().to_string(), simulated: true, simulation_succeeded: simulation.success, resolved_signers: vec![fee_payer], submit: request.submit, operator_confirmed: request.operator_confirmed, }, ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { let simulation_json = match serde_json::to_string_pretty(&simulation) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => "".to_string(), }; return std::result::Result::Err(kb_core::Error::new( error.code(), format!("{}; simulation={simulation_json}", error.message()), )); }, }; let evidence = unsigned.bind_simulation(simulation.clone()); return std::result::Result::Ok(PreparedSolanaProgramMetadataExecution { wallet, unsigned, evidence, summary: crate::DevnetSolanaProgramMetadataExecutionSummary { profile_name: profile.name.clone(), cluster: kb_lib::ExApiExecutionCluster::Devnet, genesis_hash: genesis.genesis_hash, wallet: wallet_summary, balance_lamports: balance.lamports, before, stateful_preflight, plan, latest_blockhash, fee, simulation, readiness, send_result: std::option::Option::None, confirmation: std::option::Option::None, after: std::vec::Vec::new(), post_execution: std::option::Option::None, materialized_snapshots: std::vec::Vec::new(), }, }); } fn build_intent( profile: &kb_config::ProfileConfig, request: &crate::DevnetSolanaProgramMetadataExecutionRequest, fee_payer: kb_lib::MdPubkey, ) -> kb_lib::ExMetadataSpmExecutionIntent { return kb_lib::ExMetadataSpmExecutionIntent { intent_id: request.intent_id.clone(), fee_payer: fee_payer.clone(), policy: kb_lib::ExApiExecutionPolicy { cluster: kb_lib::ExApiExecutionClusterPolicy { expected_cluster: kb_lib::ExApiExecutionCluster::Devnet, allow_mainnet: false, mainnet_confirmation: false, }, simulation: kb_lib::ExApiExecutionSimulationPolicy::Required, blockhash: kb_lib::ExApiExecutionBlockhashPolicy { kind: kb_lib::ExApiExecutionBlockhashKind::Latest, max_age_slots: std::option::Option::Some( profile.execution.recent_blockhash_max_age_slots, ), nonce_account: std::option::Option::None, nonce_authority: std::option::Option::None, }, cost_limit: kb_lib::ExApiExecutionCostLimit { max_spend_lamports: std::option::Option::Some( profile.execution.devnet_max_spend_lamports, ), max_fee_lamports: std::option::Option::Some(profile.execution.max_fee_lamports), max_compute_unit_price_micro_lamports: std::option::Option::Some( profile.execution.max_compute_unit_price_micro_lamports, ), }, authorized_signers: vec![fee_payer], dry_run: !request.submit, post_execution_validation: kb_lib::ExApiPostExecutionValidationPolicy { canonical_insert_required: true, core_extraction_required: true, decode_replay_required: true, materialization_required: true, }, }, allow_destructive_operation: request.allow_destructive_operation, operation: request.operation.clone(), }; } async fn read_snapshots( http_pool: &kb_onchain_transport::HttpEndpointPool, requests: &[kb_pipeline::SolanaProgramMetadataStatefulReadRequest], ) -> kb_core::Result> { let mut results = std::vec::Vec::with_capacity(requests.len()); for request in requests { let value = match kb_pipeline::read_solana_program_metadata_stateful_snapshot(http_pool, request) .await { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; results.push(value); } return std::result::Result::Ok(results); } fn materialize_confirmed_snapshots( snapshots: &[kb_pipeline::SolanaProgramMetadataStatefulReadResult], ) -> std::vec::Vec { return snapshots .iter() .filter_map(|result| return result.materialized_output.clone()) .collect(); } fn validate_profile( profile: &kb_config::ProfileConfig, request: &crate::DevnetSolanaProgramMetadataExecutionRequest, ) -> kb_core::Result<()> { if profile.wallet.cluster != "devnet" { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata orchestration requires a Devnet wallet profile", )); } if !profile.wallet.temporary_wallet_enabled || !profile.wallet.temporary_wallet_persist { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata orchestration requires an enabled persistent temporary wallet", )); } if !profile.execution.require_simulation { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata orchestration requires simulation", )); } if request.submit && !profile.wallet.devnet_send_enabled { return std::result::Result::Err(kb_core::Error::config( "Devnet transaction submission is disabled by the wallet profile", )); } if request.submit && profile.execution.require_operator_confirmation && !request.operator_confirmed { return std::result::Result::Err(kb_core::Error::config( "Solana Program Metadata submission requires explicit operator confirmation", )); } return std::result::Result::Ok(()); } fn validate_profile_wallet_signers( required_signers: &[std::string::String], wallet_pubkey: &str, ) -> kb_core::Result<()> { if required_signers.iter().any(|value| return value.as_str() != wallet_pubkey) { return std::result::Result::Err(kb_core::Error::new( "execution_metadata_spm_external_signer_unavailable", format!( "the Devnet Solana Program Metadata orchestrator can sign only with profile wallet {}; required signers are {}", wallet_pubkey, required_signers.join(",") ), )); } return std::result::Result::Ok(()); } #[cfg(test)] mod tests { fn wallet() -> kb_lib::MdPubkey { return kb_lib::MdPubkey(solana_pubkey::Pubkey::new_from_array([7_u8; 32]).to_string()); } #[test] fn request_rejects_destructive_operations_without_approval() { let wallet = wallet(); let mut request = crate::DevnetSolanaProgramMetadataExecutionRequest::new( "write", kb_lib::ExMetadataSpmOperation::Write { buffer: wallet.clone(), authority: wallet, offset: 0, source: kb_lib::ExMetadataSpmWriteSource::Inline { data: vec![1] }, }, ); request .preflight_reads .push(kb_pipeline::SolanaProgramMetadataStatefulReadRequest { query_role: "http_queries".to_string(), account: request.operation_target_for_test(), expected_state: kb_pipeline::SolanaProgramMetadataExpectedAccountState::Buffer, min_context_slot: std::option::Option::None, max_data_bytes: kb_pipeline::MAX_SOLANA_PROGRAM_METADATA_STATEFUL_ACCOUNT_BYTES, }); assert!(request.validate().is_err()); request.allow_destructive_operation = true; assert!(request.validate().is_ok()); } trait OperationTargetForTest { fn operation_target_for_test(&self) -> kb_lib::MdPubkey; } impl OperationTargetForTest for crate::DevnetSolanaProgramMetadataExecutionRequest { fn operation_target_for_test(&self) -> kb_lib::MdPubkey { return match &self.operation { kb_lib::ExMetadataSpmOperation::Write { buffer, .. } => buffer.clone(), _ => kb_lib::MdPubkey(kb_program_ids::SYSTEM_PROGRAM_ID.to_string()), }; } } }