v0.1.0-pre.019
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# file: kb-lib/Cargo.toml
|
||||
# version: 11
|
||||
# version: 12
|
||||
|
||||
[package]
|
||||
name = "kb-lib"
|
||||
@@ -34,6 +34,7 @@ solana-vote-interface.workspace = true
|
||||
solana-zk-elgamal-proof-interface.workspace = true
|
||||
solana-zk-sdk-pod.workspace = true
|
||||
spl-associated-token-account-interface.workspace = true
|
||||
spl-elgamal-registry-interface.workspace = true
|
||||
spl-token-group-interface.workspace = true
|
||||
spl-token-metadata-interface.workspace = true
|
||||
spl-token-2022-interface.workspace = true
|
||||
@@ -47,7 +48,6 @@ wincode.workspace = true
|
||||
solana-ed25519-program.workspace = true
|
||||
solana-secp256k1-program.workspace = true
|
||||
solana-secp256r1-program.workspace = true
|
||||
spl-elgamal-registry-interface.workspace = true
|
||||
spl-token-interface.workspace = true
|
||||
|
||||
[lints]
|
||||
|
||||
@@ -501,6 +501,10 @@ pub use self::spl::EX_SPL_ATA_CREATE_OPERATION;
|
||||
pub use self::spl::EX_SPL_ATA_RECOVER_NESTED_OPERATION;
|
||||
/// Exposes every supported ATA operation code.
|
||||
pub use self::spl::EX_SPL_ATA_SUPPORTED_OPERATION_CODES;
|
||||
/// Exposes the ElGamal registry creation operation code.
|
||||
pub use self::spl::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION;
|
||||
/// Exposes the ElGamal registry update operation code.
|
||||
pub use self::spl::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION;
|
||||
/// Exposes the stable SPL Memo add-memo operation code.
|
||||
pub use self::spl::EX_SPL_MEMO_ADD_MEMO_OPERATION;
|
||||
/// Exposes the SPL Memo payload bound.
|
||||
@@ -717,8 +721,14 @@ pub use self::spl::ExSplAssociatedTokenAccountExecutor;
|
||||
pub use self::spl::ExSplAssociatedTokenAccountOperation;
|
||||
/// Exposes the exact Token Program used by ATA derivation.
|
||||
pub use self::spl::ExSplAssociatedTokenProgram;
|
||||
/// Exposes the reserved `spl/elgamal_registry` executor.
|
||||
/// Exposes the typed SPL ElGamal registry execution intent.
|
||||
pub use self::spl::ExSplElgamalRegistryExecutionIntent;
|
||||
/// Exposes the typed SPL ElGamal registry executor.
|
||||
pub use self::spl::ExSplElgamalRegistryExecutor;
|
||||
/// Exposes one exact SPL ElGamal registry operation.
|
||||
pub use self::spl::ExSplElgamalRegistryOperation;
|
||||
/// Exposes the SPL ElGamal registry proof-location contract.
|
||||
pub use self::spl::ExSplElgamalRegistryProofLocation;
|
||||
/// Exposes the typed SPL Memo execution intent.
|
||||
pub use self::spl::ExSplMemoExecutionIntent;
|
||||
/// Exposes the SPL Memo executor.
|
||||
@@ -852,6 +862,8 @@ pub(crate) use self::solana::executor_solana_core_vote_build_prepared_plan;
|
||||
pub(crate) use self::solana::executor_solana_core_zk_elgamal_build_prepared_plan;
|
||||
/// Canonical SPL ATA tracing target.
|
||||
pub(crate) use self::spl::EX_SPL_ATA_TRACING_TARGET;
|
||||
/// Canonical SPL ElGamal registry tracing target.
|
||||
pub(crate) use self::spl::EX_SPL_ELGAMAL_REGISTRY_TRACING_TARGET;
|
||||
/// Canonical SPL Memo tracing target.
|
||||
pub(crate) use self::spl::EX_SPL_MEMO_TRACING_TARGET;
|
||||
/// Maximum ordered multisig signer occurrences for SPL Token-2022.
|
||||
@@ -864,6 +876,8 @@ pub(crate) use self::spl::EX_SPL_TOKEN2022_MAX_UI_AMOUNT_BYTES;
|
||||
pub(crate) use self::spl::EX_SPL_TOKEN2022_TRACING_TARGET;
|
||||
/// Internal SPL ATA plan builder.
|
||||
pub(crate) use self::spl::executor_spl_ata_build_prepared_plan;
|
||||
/// Internal SPL ElGamal registry plan builder.
|
||||
pub(crate) use self::spl::executor_spl_elgamal_registry_build_prepared_plan;
|
||||
/// Internal SPL Memo plan builder.
|
||||
pub(crate) use self::spl::executor_spl_memo_build_prepared_plan;
|
||||
/// Internal SPL Token-2022 prepared-plan builder.
|
||||
@@ -873,7 +887,7 @@ pub(crate) use self::spl::executor_spl_token2022_build_prepared_plan;
|
||||
mod reserved_executor_tests {
|
||||
#[test]
|
||||
fn every_reserved_executor_is_registered_and_builds_only_an_empty_plan() {
|
||||
let executors: [&dyn crate::ExApiInstructionExecutor; 100] = [
|
||||
let executors: [&dyn crate::ExApiInstructionExecutor; 99] = [
|
||||
&crate::ExAdapterSaberDecimalWrapperExecutor,
|
||||
&crate::ExAdminJupiterLockExecutor,
|
||||
&crate::ExAdminPumpFeesExecutor,
|
||||
@@ -952,7 +966,6 @@ mod reserved_executor_tests {
|
||||
&crate::ExRouterOkxLabsV2Executor,
|
||||
&crate::ExRwaOndoGlobalMarketsExecutor,
|
||||
&crate::ExSplAccountCompressionExecutor,
|
||||
&crate::ExSplElgamalRegistryExecutor,
|
||||
&crate::ExSplNoopExecutor,
|
||||
&crate::ExSplSinglePoolExecutor,
|
||||
&crate::ExSplStakePoolExecutor,
|
||||
@@ -975,7 +988,7 @@ mod reserved_executor_tests {
|
||||
&crate::ExWalletJupiterApeproSmartWalletExecutor,
|
||||
&crate::ExWeightedSwapStabbleExecutor,
|
||||
];
|
||||
assert_eq!(executors.len(), 100);
|
||||
assert_eq!(executors.len(), 99);
|
||||
for executor in executors {
|
||||
assert!(!executor.program_ids().is_empty());
|
||||
for program_id in executor.program_ids() {
|
||||
|
||||
@@ -31,8 +31,18 @@ pub use self::associated_token_account::ExSplAssociatedTokenAccountExecutor;
|
||||
pub use self::associated_token_account::ExSplAssociatedTokenAccountOperation;
|
||||
/// Exposes the exact Token Program used by ATA derivation.
|
||||
pub use self::associated_token_account::ExSplAssociatedTokenProgram;
|
||||
/// Exposes the reserved `spl/elgamal_registry` executor.
|
||||
/// Exposes the ElGamal registry creation operation code.
|
||||
pub use self::elgamal_registry::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION;
|
||||
/// Exposes the ElGamal registry update operation code.
|
||||
pub use self::elgamal_registry::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION;
|
||||
/// Exposes the typed SPL ElGamal registry execution intent.
|
||||
pub use self::elgamal_registry::ExSplElgamalRegistryExecutionIntent;
|
||||
/// Exposes the typed SPL ElGamal registry executor.
|
||||
pub use self::elgamal_registry::ExSplElgamalRegistryExecutor;
|
||||
/// Exposes one exact SPL ElGamal registry operation.
|
||||
pub use self::elgamal_registry::ExSplElgamalRegistryOperation;
|
||||
/// Exposes the SPL ElGamal registry proof-location contract.
|
||||
pub use self::elgamal_registry::ExSplElgamalRegistryProofLocation;
|
||||
/// Exposes the stable SPL Memo add-memo operation code.
|
||||
pub use self::memo::EX_SPL_MEMO_ADD_MEMO_OPERATION;
|
||||
/// Exposes the SPL Memo payload bound.
|
||||
@@ -302,6 +312,10 @@ pub use self::token2022::executor_spl_token2022_validate_confidential_proof_refe
|
||||
pub(crate) use self::associated_token_account::EX_SPL_ATA_TRACING_TARGET;
|
||||
/// Internal SPL ATA plan builder.
|
||||
pub(crate) use self::associated_token_account::executor_spl_ata_build_prepared_plan;
|
||||
/// Canonical SPL ElGamal registry tracing target.
|
||||
pub(crate) use self::elgamal_registry::EX_SPL_ELGAMAL_REGISTRY_TRACING_TARGET;
|
||||
/// Internal SPL ElGamal registry plan builder.
|
||||
pub(crate) use self::elgamal_registry::executor_spl_elgamal_registry_build_prepared_plan;
|
||||
/// Canonical SPL Memo tracing target.
|
||||
pub(crate) use self::memo::EX_SPL_MEMO_TRACING_TARGET;
|
||||
/// Internal SPL Memo plan builder.
|
||||
|
||||
@@ -1,49 +1,27 @@
|
||||
// file: kb-lib/src/executor/spl/elgamal_registry.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
//! Reserved executor for `spl_elgamal_registry`.
|
||||
//! Typed executor for the SPL ElGamal public-key registry.
|
||||
|
||||
/// Reserved executor for the `spl_elgamal_registry` program surface.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ExSplElgamalRegistryExecutor;
|
||||
mod builder;
|
||||
mod constants;
|
||||
mod executor;
|
||||
mod intent;
|
||||
|
||||
impl crate::ExApiInstructionExecutor for crate::ExSplElgamalRegistryExecutor {
|
||||
fn executor_name(&self) -> &'static str {
|
||||
return "kb_executor_spl_elgamal_registry";
|
||||
}
|
||||
/// Exposes the typed ElGamal registry executor.
|
||||
pub use self::executor::ExSplElgamalRegistryExecutor;
|
||||
/// Stable operation code for registry creation.
|
||||
pub use self::intent::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION;
|
||||
/// Stable operation code for registry update.
|
||||
pub use self::intent::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION;
|
||||
/// Exposes the complete typed execution intent.
|
||||
pub use self::intent::ExSplElgamalRegistryExecutionIntent;
|
||||
/// Exposes one exact registry operation.
|
||||
pub use self::intent::ExSplElgamalRegistryOperation;
|
||||
/// Exposes the proof-location contract.
|
||||
pub use self::intent::ExSplElgamalRegistryProofLocation;
|
||||
|
||||
fn executor_version(&self) -> &'static str {
|
||||
return env!("CARGO_PKG_VERSION");
|
||||
}
|
||||
|
||||
fn program_ids(&self) -> &'static [&'static str] {
|
||||
return &[kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID];
|
||||
}
|
||||
|
||||
fn supports_request(
|
||||
&self,
|
||||
request: &crate::ExApiExecutionRequest,
|
||||
) -> crate::ExApiExecutionSupport {
|
||||
if crate::ExApiInstructionExecutor::handles_program_id(self, &request.program_id) {
|
||||
return crate::ExApiExecutionSupport::Maybe;
|
||||
}
|
||||
return crate::ExApiExecutionSupport::No;
|
||||
}
|
||||
|
||||
fn build_plan(
|
||||
&self,
|
||||
_request: &crate::ExApiExecutionRequest,
|
||||
) -> kb_core::Result<crate::ExApiExecutionPlan> {
|
||||
let payload_json = match crate::executor_api_serialize_payload_json(
|
||||
&serde_json::json!({"status":"reserved_executor","surface":"spl_elgamal_registry"}),
|
||||
) {
|
||||
std::result::Result::Ok(serialized) => serialized,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return std::result::Result::Ok(crate::ExApiExecutionPlan {
|
||||
executor_name: "kb_executor_spl_elgamal_registry".to_string(),
|
||||
instruction_count: 0,
|
||||
payload_json,
|
||||
});
|
||||
}
|
||||
}
|
||||
/// Crate-root access to the exact ElGamal registry plan builder.
|
||||
pub(crate) use self::builder::executor_spl_elgamal_registry_build_prepared_plan;
|
||||
/// Canonical tracing target for the SPL ElGamal registry executor.
|
||||
pub(crate) use self::constants::EX_SPL_ELGAMAL_REGISTRY_TRACING_TARGET;
|
||||
|
||||
281
kb-lib/src/executor/spl/elgamal_registry/builder.rs
Normal file
281
kb-lib/src/executor/spl/elgamal_registry/builder.rs
Normal file
@@ -0,0 +1,281 @@
|
||||
// file: kb-lib/src/executor/spl/elgamal_registry/builder.rs
|
||||
// version: 4
|
||||
|
||||
//! 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,
|
||||
) -> kb_core::Result<crate::ExApiPreparedExecutionPlan> {
|
||||
if intent.intent_id.trim().is_empty() {
|
||||
return std::result::Result::Err(kb_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(kb_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(kb_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(kb_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(kb_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(kb_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(kb_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<solana_instruction::Instruction> = match instructions {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let planned: Vec<crate::ExApiPlannedInstruction> = 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::EX_SPL_ELGAMAL_REGISTRY_TRACING_TARGET,
|
||||
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("kb_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,
|
||||
>,
|
||||
) -> kb_core::Result<std::vec::Vec<solana_instruction::Instruction>> {
|
||||
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(kb_core::Error::new(
|
||||
"execution_spl_elgamal_registry_builder_failed",
|
||||
error.to_string(),
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_address(value: &crate::MdPubkey, field: &str) -> kb_core::Result<solana_pubkey::Pubkey> {
|
||||
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(kb_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(kb_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(kb_program_ids::VOTE_PROGRAM_ID),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
crate::ExSplElgamalRegistryOperation::UpdateRegistry {
|
||||
owner,
|
||||
proof: crate::ExSplElgamalRegistryProofLocation::ContextStateAccount {
|
||||
account: pubkey(kb_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,
|
||||
kb_program_ids::SPL_TOKEN2022_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(kb_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");
|
||||
}
|
||||
}
|
||||
8
kb-lib/src/executor/spl/elgamal_registry/constants.rs
Normal file
8
kb-lib/src/executor/spl/elgamal_registry/constants.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
// file: kb-lib/src/executor/spl/elgamal_registry/constants.rs
|
||||
// version: 2
|
||||
|
||||
//! Executor-local constants.
|
||||
|
||||
/// Canonical tracing target for this crate.
|
||||
pub(crate) const EX_SPL_ELGAMAL_REGISTRY_TRACING_TARGET: &str =
|
||||
"kb-lib.executor.spl.elgamal_registry";
|
||||
167
kb-lib/src/executor/spl/elgamal_registry/executor.rs
Normal file
167
kb-lib/src/executor/spl/elgamal_registry/executor.rs
Normal file
@@ -0,0 +1,167 @@
|
||||
// file: kb-lib/src/executor/spl/elgamal_registry/executor.rs
|
||||
// version: 2
|
||||
|
||||
//! Exact capability dispatch for the SPL ElGamal registry.
|
||||
|
||||
/// Typed SPL ElGamal registry executor.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ExSplElgamalRegistryExecutor;
|
||||
|
||||
impl crate::ExSplElgamalRegistryExecutor {
|
||||
fn exact_capability(
|
||||
&self,
|
||||
program_id: &crate::MdProgramId,
|
||||
operation_code: &str,
|
||||
) -> crate::ExApiExecutionCapability {
|
||||
if program_id.0 != kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID {
|
||||
return crate::ExApiExecutionCapability::unsupported(
|
||||
"execution_spl_elgamal_registry_program_not_owned",
|
||||
format!("program {} is not the SPL ElGamal registry", program_id.0),
|
||||
);
|
||||
}
|
||||
return match operation_code {
|
||||
crate::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION
|
||||
| crate::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION => {
|
||||
crate::ExApiExecutionCapability::supported(operation_code)
|
||||
},
|
||||
_ => crate::ExApiExecutionCapability::unsupported(
|
||||
"execution_spl_elgamal_registry_operation_unsupported",
|
||||
format!("ElGamal registry operation {operation_code} is not implemented"),
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::ExApiTypedInstructionExecutor for crate::ExSplElgamalRegistryExecutor {
|
||||
type Intent = crate::ExSplElgamalRegistryExecutionIntent;
|
||||
|
||||
fn capability(
|
||||
&self,
|
||||
program_id: &crate::MdProgramId,
|
||||
operation_code: &str,
|
||||
) -> crate::ExApiExecutionCapability {
|
||||
return self.exact_capability(program_id, operation_code);
|
||||
}
|
||||
|
||||
fn build_prepared_plan(
|
||||
&self,
|
||||
intent: &Self::Intent,
|
||||
) -> kb_core::Result<crate::ExApiPreparedExecutionPlan> {
|
||||
let program_id = crate::MdProgramId(std::string::String::from(
|
||||
kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID,
|
||||
));
|
||||
return match self.exact_capability(&program_id, intent.operation.operation_code()) {
|
||||
crate::ExApiExecutionCapability::Supported { operation_code: _ } => {
|
||||
crate::executor_spl_elgamal_registry_build_prepared_plan(intent)
|
||||
},
|
||||
crate::ExApiExecutionCapability::Unsupported { reason_code, reason } => {
|
||||
std::result::Result::Err(kb_core::Error::new(reason_code, reason))
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::ExApiInstructionExecutor for crate::ExSplElgamalRegistryExecutor {
|
||||
fn executor_name(&self) -> &'static str {
|
||||
return "kb_executor_spl_elgamal_registry";
|
||||
}
|
||||
fn executor_version(&self) -> &'static str {
|
||||
return env!("CARGO_PKG_VERSION");
|
||||
}
|
||||
fn program_ids(&self) -> &'static [&'static str] {
|
||||
return &[kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID];
|
||||
}
|
||||
fn supports_request(
|
||||
&self,
|
||||
request: &crate::ExApiExecutionRequest,
|
||||
) -> crate::ExApiExecutionSupport {
|
||||
return if self
|
||||
.exact_capability(&request.program_id, &request.operation_code)
|
||||
.is_supported()
|
||||
{
|
||||
crate::ExApiExecutionSupport::Yes
|
||||
} else {
|
||||
crate::ExApiExecutionSupport::No
|
||||
};
|
||||
}
|
||||
fn build_plan(
|
||||
&self,
|
||||
request: &crate::ExApiExecutionRequest,
|
||||
) -> kb_core::Result<crate::ExApiExecutionPlan> {
|
||||
match self.exact_capability(&request.program_id, &request.operation_code) {
|
||||
crate::ExApiExecutionCapability::Supported { operation_code: _ } => {},
|
||||
crate::ExApiExecutionCapability::Unsupported { reason_code, reason } => {
|
||||
return std::result::Result::Err(kb_core::Error::new(reason_code, reason));
|
||||
},
|
||||
}
|
||||
let intent = match serde_json::from_str::<crate::ExSplElgamalRegistryExecutionIntent>(
|
||||
&request.payload_json,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"execution_spl_elgamal_registry_intent_deserialize_failed",
|
||||
error.to_string(),
|
||||
));
|
||||
},
|
||||
};
|
||||
if intent.operation.operation_code() != request.operation_code {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"execution_operation_code_mismatch",
|
||||
"request and typed intent operations differ",
|
||||
));
|
||||
}
|
||||
let prepared =
|
||||
match crate::ExApiTypedInstructionExecutor::build_prepared_plan(self, &intent) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let payload = match serde_json::to_value(&prepared) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"execution_spl_elgamal_registry_plan_serialize_failed",
|
||||
error.to_string(),
|
||||
));
|
||||
},
|
||||
};
|
||||
let payload_json = match crate::executor_api_serialize_payload_json(&payload) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return std::result::Result::Ok(crate::ExApiExecutionPlan {
|
||||
executor_name: std::string::String::from("kb_executor_spl_elgamal_registry"),
|
||||
instruction_count: prepared.instructions.len(),
|
||||
payload_json,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn program_and_operation_dispatch_are_exact() {
|
||||
let executor = crate::ExSplElgamalRegistryExecutor;
|
||||
for operation in [
|
||||
crate::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION,
|
||||
crate::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION,
|
||||
] {
|
||||
let capability = crate::ExApiTypedInstructionExecutor::capability(
|
||||
&executor,
|
||||
&crate::MdProgramId(std::string::String::from(
|
||||
kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID,
|
||||
)),
|
||||
operation,
|
||||
);
|
||||
assert!(capability.is_supported());
|
||||
}
|
||||
let foreign = crate::ExApiTypedInstructionExecutor::capability(
|
||||
&executor,
|
||||
&crate::MdProgramId(std::string::String::from(
|
||||
kb_program_ids::SPL_TOKEN2022_PROGRAM_ID,
|
||||
)),
|
||||
crate::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION,
|
||||
);
|
||||
assert!(!foreign.is_supported());
|
||||
}
|
||||
}
|
||||
86
kb-lib/src/executor/spl/elgamal_registry/intent.rs
Normal file
86
kb-lib/src/executor/spl/elgamal_registry/intent.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
// file: kb-lib/src/executor/spl/elgamal_registry/intent.rs
|
||||
// version: 2
|
||||
|
||||
//! Typed intents for the SPL ElGamal public-key registry.
|
||||
|
||||
use ts_rs::TS; // rust-rules: derive-import
|
||||
|
||||
/// Stable operation code for registry creation.
|
||||
pub const EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION: &str = "spl_elgamal_registry.create_registry";
|
||||
/// Stable operation code for registry update.
|
||||
pub const EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION: &str = "spl_elgamal_registry.update_registry";
|
||||
|
||||
/// Exact location of the public-key validity proof.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
||||
#[serde(tag = "location", rename_all = "snake_case")]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/kb_lib/executor/spl/elgamal_registry/intent/ExSplElgamalRegistryProofLocation.ts"
|
||||
)]
|
||||
pub enum ExSplElgamalRegistryProofLocation {
|
||||
/// A pre-verified proof context-state account.
|
||||
ContextStateAccount {
|
||||
/// Context-state account owned by the native ZK ElGamal proof program.
|
||||
account: crate::MdPubkey,
|
||||
},
|
||||
/// Inline `PubkeyValidity` proof placed immediately after the registry instruction.
|
||||
Inline {
|
||||
/// Canonical raw `PubkeyValidityProofData` bytes encoded as base64.
|
||||
proof_data_base64: std::string::String,
|
||||
},
|
||||
}
|
||||
|
||||
/// Typed registry operation.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/kb_lib/executor/spl/elgamal_registry/intent/ExSplElgamalRegistryOperation.ts"
|
||||
)]
|
||||
pub enum ExSplElgamalRegistryOperation {
|
||||
/// Create the deterministic registry PDA for one owner.
|
||||
CreateRegistry {
|
||||
/// Wallet that owns and signs for the registry.
|
||||
owner: crate::MdPubkey,
|
||||
/// Proof location.
|
||||
proof: crate::ExSplElgamalRegistryProofLocation,
|
||||
},
|
||||
/// Update the registry with a newly proven ElGamal public key.
|
||||
UpdateRegistry {
|
||||
/// Wallet that owns and signs for the registry.
|
||||
owner: crate::MdPubkey,
|
||||
/// Proof location.
|
||||
proof: crate::ExSplElgamalRegistryProofLocation,
|
||||
},
|
||||
}
|
||||
|
||||
impl crate::ExSplElgamalRegistryOperation {
|
||||
/// Returns the stable operation code.
|
||||
pub fn operation_code(&self) -> &'static str {
|
||||
return match self {
|
||||
Self::CreateRegistry { owner: _, proof: _ } => {
|
||||
crate::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION
|
||||
},
|
||||
Self::UpdateRegistry { owner: _, proof: _ } => {
|
||||
crate::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Complete typed execution intent.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/kb_lib/executor/spl/elgamal_registry/intent/ExSplElgamalRegistryExecutionIntent.ts"
|
||||
)]
|
||||
pub struct ExSplElgamalRegistryExecutionIntent {
|
||||
/// Caller-provided correlation identifier.
|
||||
pub intent_id: std::string::String,
|
||||
/// Transaction fee payer.
|
||||
pub fee_payer: crate::MdPubkey,
|
||||
/// Conservative common execution policy.
|
||||
pub policy: crate::ExApiExecutionPolicy,
|
||||
/// Registry operation.
|
||||
pub operation: crate::ExSplElgamalRegistryOperation,
|
||||
}
|
||||
@@ -571,6 +571,10 @@ pub use self::executor::EX_SPL_ATA_CREATE_OPERATION;
|
||||
pub use self::executor::EX_SPL_ATA_RECOVER_NESTED_OPERATION;
|
||||
/// Exposes every supported ATA operation code.
|
||||
pub use self::executor::EX_SPL_ATA_SUPPORTED_OPERATION_CODES;
|
||||
/// Exposes the SPL ElGamal registry creation operation code.
|
||||
pub use self::executor::EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION;
|
||||
/// Exposes the SPL ElGamal registry update operation code.
|
||||
pub use self::executor::EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION;
|
||||
/// Exposes the stable SPL Memo add-memo operation code.
|
||||
pub use self::executor::EX_SPL_MEMO_ADD_MEMO_OPERATION;
|
||||
/// Exposes the SPL Memo payload bound.
|
||||
@@ -1023,8 +1027,14 @@ pub use self::executor::ExSplAssociatedTokenAccountExecutor;
|
||||
pub use self::executor::ExSplAssociatedTokenAccountOperation;
|
||||
/// Exposes the exact Token Program used by ATA derivation.
|
||||
pub use self::executor::ExSplAssociatedTokenProgram;
|
||||
/// Exposes the reserved `ExSplElgamalRegistryExecutor` implementation.
|
||||
/// Exposes the typed SPL ElGamal registry execution intent.
|
||||
pub use self::executor::ExSplElgamalRegistryExecutionIntent;
|
||||
/// Exposes the typed SPL ElGamal registry executor.
|
||||
pub use self::executor::ExSplElgamalRegistryExecutor;
|
||||
/// Exposes one exact SPL ElGamal registry operation.
|
||||
pub use self::executor::ExSplElgamalRegistryOperation;
|
||||
/// Exposes the SPL ElGamal registry proof-location contract.
|
||||
pub use self::executor::ExSplElgamalRegistryProofLocation;
|
||||
/// Exposes the typed SPL Memo execution intent.
|
||||
pub use self::executor::ExSplMemoExecutionIntent;
|
||||
/// Exposes the SPL Memo executor.
|
||||
@@ -1688,6 +1698,8 @@ pub(crate) use self::decoder::decoder_spl_token2022_payload_tag;
|
||||
pub(crate) use self::executor::EX_SOLANA_CORE_TRACING_TARGET;
|
||||
/// Canonical SPL Memo tracing target.
|
||||
pub(crate) use self::executor::EX_SPL_ATA_TRACING_TARGET;
|
||||
/// Canonical tracing target for the SPL ElGamal registry executor.
|
||||
pub(crate) use self::executor::EX_SPL_ELGAMAL_REGISTRY_TRACING_TARGET;
|
||||
/// Canonical SPL Memo tracing target.
|
||||
pub(crate) use self::executor::EX_SPL_MEMO_TRACING_TARGET;
|
||||
/// Maximum ordered multisig signer occurrences for SPL Token-2022.
|
||||
@@ -1736,6 +1748,8 @@ pub(crate) use self::executor::executor_solana_core_vote_build_prepared_plan;
|
||||
pub(crate) use self::executor::executor_solana_core_zk_elgamal_build_prepared_plan;
|
||||
/// Internal SPL Memo plan builder.
|
||||
pub(crate) use self::executor::executor_spl_ata_build_prepared_plan;
|
||||
/// Internal SPL ElGamal registry plan builder.
|
||||
pub(crate) use self::executor::executor_spl_elgamal_registry_build_prepared_plan;
|
||||
/// Internal SPL Memo plan builder.
|
||||
pub(crate) use self::executor::executor_spl_memo_build_prepared_plan;
|
||||
/// Internal SPL Token-2022 prepared-plan builder.
|
||||
|
||||
Reference in New Issue
Block a user