// file: ks-lib/src/executor/spl/elgamal_registry/builder.rs // version: 9 //! Official registry builders and conservative plan validation. use base64::Engine; // rust-rules: trait-import use std::str::FromStr; // rust-rules: trait-import pub(crate) fn executor_spl_elgamal_registry_build_prepared_plan( intent: &crate::ExSplElgamalRegistryExecutionIntent, ) -> ks_core::Result { if intent.intent_id.trim().is_empty() { return std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_intent_id_empty", "ElGamal registry execution intent id must not be empty", )); } if intent.policy.simulation != crate::ExApiExecutionSimulationPolicy::Required { return std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_simulation_required", "ElGamal registry execution requires simulation", )); } match intent.policy.cost_limit.max_fee_lamports { std::option::Option::Some(value) if value > 0 => {}, std::option::Option::Some(_) | std::option::Option::None => { return std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_fee_limit_missing", "ElGamal registry execution requires a positive fee ceiling", )); }, } let validation = &intent.policy.post_execution_validation; if !validation.canonical_insert_required || !validation.core_extraction_required || !validation.decode_replay_required || !validation.materialization_required { return std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_post_validation_required", "ElGamal registry execution requires canonical insert, core extraction, decode replay and materialization", )); } let fee_payer = match parse_address(&intent.fee_payer, "fee_payer") { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let (owner_model, proof, operation_code, create) = match &intent.operation { crate::ExSplElgamalRegistryOperation::CreateRegistry { owner, proof } => { (owner, proof, crate::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION, true) }, crate::ExSplElgamalRegistryOperation::UpdateRegistry { owner, proof } => { (owner, proof, crate::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION, false) }, }; let owner = match parse_address(owner_model, "owner") { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let instructions = match proof { crate::ExSplElgamalRegistryProofLocation::ContextStateAccount { account } => { let context = match parse_address(account, "context_state_account") { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let location = spl_token_confidential_transfer_proof_extraction::instruction::ProofLocation::ContextStateAccount(&context); build_official(create, &owner, location) }, crate::ExSplElgamalRegistryProofLocation::Inline { proof_data_base64 } => { let bytes = match base64::engine::general_purpose::STANDARD .decode(proof_data_base64.as_bytes()) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { return std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_proof_base64_invalid", error.to_string(), )); }, }; let expected = std::mem::size_of::< solana_zk_elgamal_proof_interface::proof_data::PubkeyValidityProofData, >(); if bytes.len() != expected { return std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_proof_size_invalid", format!( "PubkeyValidityProofData requires {expected} bytes, received {}", bytes.len() ), )); } let proof_data = bytemuck::pod_read_unaligned::< solana_zk_elgamal_proof_interface::proof_data::PubkeyValidityProofData, >(bytes.as_slice()); let offset = match std::num::NonZeroI8::new(1) { std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_internal_offset_invalid", "inline proof offset must be one", )); }, }; let location = spl_token_confidential_transfer_proof_extraction::instruction::ProofLocation::InstructionOffset(offset, &proof_data); build_official(create, &owner, location) }, }; let instructions: Vec = match instructions { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let planned: Vec = instructions .iter() .map(|instruction| return planned_instruction(operation_code, instruction)) .collect(); let mut required_signers = vec![crate::ExApiRequiredSigner { pubkey: intent.fee_payer.clone(), role: std::string::String::from("fee_payer"), }]; if intent.fee_payer != *owner_model { required_signers.push(crate::ExApiRequiredSigner { pubkey: owner_model.clone(), role: std::string::String::from("registry_owner"), }); } tracing::debug!( target: crate::TRACING_TARGET_EXECUTOR_SPL_ELGAMAL_REGISTRY, action = "build_prepared_plan", intent_id = %intent.intent_id, operation_code, owner = %owner_model.0, instruction_count = planned.len(), "built SPL ElGamal registry execution plan" ); return std::result::Result::Ok(crate::ExApiPreparedExecutionPlan { executor_name: std::string::String::from("ks-lib-executor.spl.elgamal_registry"), executor_version: std::string::String::from(env!("CARGO_PKG_VERSION")), intent_id: intent.intent_id.clone(), operation_code: std::string::String::from(operation_code), fee_payer: crate::MdPubkey(fee_payer.to_string()), instructions: planned, required_signers, policy: intent.policy.clone(), requested_spend_lamports: 0, requested_compute_unit_price_micro_lamports: std::option::Option::None, }); } fn build_official( create: bool, owner: &solana_pubkey::Pubkey, location: spl_token_confidential_transfer_proof_extraction::instruction::ProofLocation< solana_zk_elgamal_proof_interface::proof_data::PubkeyValidityProofData, >, ) -> ks_core::Result> { let result = if create { spl_elgamal_registry_interface::instruction::create_registry(owner, location) } else { spl_elgamal_registry_interface::instruction::update_registry(owner, location) }; return match result { std::result::Result::Ok(value) => std::result::Result::Ok(value), std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_builder_failed", error.to_string(), )), }; } fn parse_address(value: &crate::MdPubkey, field: &str) -> ks_core::Result { return match solana_pubkey::Pubkey::from_str(value.0.as_str()) { std::result::Result::Ok(address) => std::result::Result::Ok(address), std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new( "execution_spl_elgamal_registry_pubkey_invalid", format!("{field}: {error}"), )), }; } fn planned_instruction( operation_code: &str, instruction: &solana_instruction::Instruction, ) -> crate::ExApiPlannedInstruction { return crate::ExApiPlannedInstruction { program_id: crate::MdProgramId(instruction.program_id.to_string()), operation_code: std::string::String::from(operation_code), accounts: instruction .accounts .iter() .map(|account| { return crate::ExApiPlannedAccount { pubkey: crate::MdPubkey(account.pubkey.to_string()), is_signer: account.is_signer, is_writable: account.is_writable, }; }) .collect(), data: instruction.data.clone(), }; } #[cfg(test)] mod tests { fn pubkey(value: &str) -> crate::MdPubkey { return crate::MdPubkey(std::string::String::from(value)); } fn intent(create: bool) -> crate::ExSplElgamalRegistryExecutionIntent { let owner = pubkey(ks_program_ids::SYSTEM_PROGRAM_ID); return crate::ExSplElgamalRegistryExecutionIntent { intent_id: std::string::String::from("registry-intent"), fee_payer: owner.clone(), policy: crate::ExApiExecutionPolicy { cost_limit: crate::ExApiExecutionCostLimit { max_spend_lamports: std::option::Option::Some(0), max_fee_lamports: std::option::Option::Some(20_000), max_compute_unit_price_micro_lamports: std::option::Option::None, }, authorized_signers: vec![owner.clone()], dry_run: true, post_execution_validation: crate::ExApiPostExecutionValidationPolicy { canonical_insert_required: true, core_extraction_required: true, decode_replay_required: true, materialization_required: true, }, ..crate::ExApiExecutionPolicy::default() }, operation: if create { crate::ExSplElgamalRegistryOperation::CreateRegistry { owner, proof: crate::ExSplElgamalRegistryProofLocation::ContextStateAccount { account: pubkey(ks_program_ids::VOTE_PROGRAM_ID), }, } } else { crate::ExSplElgamalRegistryOperation::UpdateRegistry { owner, proof: crate::ExSplElgamalRegistryProofLocation::ContextStateAccount { account: pubkey(ks_program_ids::VOTE_PROGRAM_ID), }, } }, }; } #[test] fn create_and_update_use_official_registry_wire_and_accounts() { for create in [true, false] { let plan = crate::executor_spl_elgamal_registry_build_prepared_plan(&intent(create)) .unwrap_or_else(|error| panic!("registry plan failed: {error}")); assert_eq!(plan.instructions.len(), 1); assert_eq!( plan.instructions[0].program_id.0, ks_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID ); assert_eq!(plan.instructions[0].data, if create { vec![0, 0] } else { vec![1, 0] }); assert_eq!(plan.required_signers.len(), 1); } } #[test] fn optional_simulation_and_invalid_inline_proof_fail_closed() { let mut value = intent(true); value.policy.simulation = crate::ExApiExecutionSimulationPolicy::Optional; let error = crate::executor_spl_elgamal_registry_build_prepared_plan(&value) .expect_err("optional simulation must fail"); assert_eq!(error.code(), "execution_spl_elgamal_registry_simulation_required"); value = intent(true); value.operation = crate::ExSplElgamalRegistryOperation::CreateRegistry { owner: pubkey(ks_program_ids::SYSTEM_PROGRAM_ID), proof: crate::ExSplElgamalRegistryProofLocation::Inline { proof_data_base64: std::string::String::from("AA=="), }, }; let error = crate::executor_spl_elgamal_registry_build_prepared_plan(&value) .expect_err("invalid proof size must fail"); assert_eq!(error.code(), "execution_spl_elgamal_registry_proof_size_invalid"); } }