This commit is contained in:
2026-07-23 16:37:12 +02:00
parent 99c345f2f2
commit 0da75c1311
2159 changed files with 230833 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
// file: kb_decoder_spl_elgamal_registry/src/constants.rs
// version: 2
//! Constants for the SPL ElGamal registry decoder.
pub(crate) const SURFACE_CODE: &str = "spl_elgamal_registry";
pub(crate) const EVENT_VERSION: u32 = 1;
pub(crate) const MAX_INSTRUCTION_BYTES: usize = 16;
/// Canonical tracing target for this crate.
pub(crate) const TRACING_TARGET: &str = "kb_decoder_spl_elgamal_registry";

View File

@@ -0,0 +1,256 @@
// file: kb_decoder_spl_elgamal_registry/src/decoder.rs
// version: 6
//! Exact dispatch for the SPL ElGamal registry program.
const SURFACES: &[kb_decoder_api::DecoderSurface] = &[kb_decoder_api::DecoderSurface {
program_id: kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID,
surface_code: crate::SURFACE_CODE,
priority: 100,
}];
const PROGRAM_IDS: &[&str] = &[kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID];
/// Decoder for the dedicated Token-2022 ElGamal public-key registry program.
#[derive(Clone, Debug, Default)]
pub struct SplElgamalRegistryDecoder;
impl kb_decoder_api::ProtocolDecoder for crate::SplElgamalRegistryDecoder {
fn decoder_name(&self) -> &'static str {
return "kb_decoder_spl_elgamal_registry";
}
fn decoder_version(&self) -> &'static str {
return env!("CARGO_PKG_VERSION");
}
fn program_ids(&self) -> &'static [&'static str] {
return PROGRAM_IDS;
}
fn supports_observation(
&self,
observation: &kb_model::ProgramObservation,
) -> kb_decoder_api::DecoderSupport {
return if kb_decoder_api::ProtocolDecoder::handles_program_id(self, &observation.program_id)
{
kb_decoder_api::DecoderSupport::Yes
} else {
kb_decoder_api::DecoderSupport::No
};
}
fn decode_observation(
&self,
_observation: &kb_model::ProgramObservation,
) -> kb_core::Result<std::vec::Vec<kb_model::DecodedProtocolEvent>> {
return std::result::Result::Ok(std::vec::Vec::new());
}
}
impl kb_decoder_api::InstructionDecoder for crate::SplElgamalRegistryDecoder {
fn identity(&self) -> kb_decoder_api::DecoderIdentity {
return kb_decoder_api::DecoderIdentity {
name: "spl_elgamal_registry".to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
};
}
fn surfaces(&self) -> &'static [kb_decoder_api::DecoderSurface] {
return SURFACES;
}
fn coverage(&self) -> std::vec::Vec<kb_decoder_api::DecoderCoverageDeclaration> {
return [(0_u8, "create_registry"), (1_u8, "update_registry")]
.into_iter()
.map(|(tag, code)| {
return kb_decoder_api::DecoderCoverageDeclaration {
program_id: kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID
.to_string(),
surface_code: std::option::Option::Some(crate::SURFACE_CODE.to_string()),
entry_kind: kb_decoder_api::DecoderCoverageEntryKind::Instruction,
entry_code: code.to_string(),
discriminator_hex: std::option::Option::Some(format!("{tag:02x}")),
historical: false,
};
})
.collect();
}
fn recognize(
&self,
input: &kb_store_core::CoreInstructionReplayInput,
) -> kb_decoder_api::DecoderRecognition {
if input.program_id != kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID {
return kb_decoder_api::DecoderRecognition::incompatible();
}
let entry = input
.instruction_payload_json
.as_ref()
.and_then(|payload| return payload.get("dataBase64"))
.and_then(serde_json::Value::as_str)
.and_then(|encoded| {
use base64::Engine; // rust-rules: trait-import
return base64::engine::general_purpose::STANDARD.decode(encoded.as_bytes()).ok();
})
.and_then(|bytes| return bytes.first().copied())
.and_then(|tag| {
return match tag {
0 => std::option::Option::Some("create_registry".to_string()),
1 => std::option::Option::Some("update_registry".to_string()),
_ => std::option::Option::None,
};
});
return kb_decoder_api::DecoderRecognition::compatible(
entry.is_some(),
100,
std::option::Option::Some(crate::SURFACE_CODE.to_string()),
entry,
std::option::Option::None,
);
}
fn decode(
&self,
input: &kb_store_core::CoreInstructionReplayInput,
) -> kb_decoder_api::DecoderExecutionResult {
if input.program_id != kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID {
return kb_decoder_api::DecoderExecutionResult::unsupported(std::option::Option::None);
}
let result = crate::decode(input);
if matches!(
result.status,
kb_decoder_api::DecoderOutcomeStatus::Failed
| kb_decoder_api::DecoderOutcomeStatus::Unsupported
) {
tracing::error!(
target: crate::TRACING_TARGET,
action = "decode_failure",
signature = %input.signature,
slot = input.slot,
instruction_path = %input.instruction_path,
program_id = %input.program_id,
processor_name = "spl_elgamal_registry",
processor_version = env!("CARGO_PKG_VERSION"),
input_key = %input.replay_input_key,
payload_hash = ?input.instruction_payload_hash,
transaction_failed = input.transaction_failed,
result_status = ?result.status,
diagnostics = ?result.diagnostics,
"SPL ElGamal registry instruction was not decoded successfully"
);
}
tracing::debug!(
target: crate::TRACING_TARGET,
action = "decode",
signature = %input.signature,
instruction_path = %input.instruction_path,
program_id = %input.program_id,
transaction_failed = input.transaction_failed,
result_status = ?result.status,
observation_count = result.observations.len(),
"SPL ElGamal registry instruction decode completed"
);
return result;
}
}
#[cfg(test)]
mod tests {
use base64::Engine; // rust-rules: trait-import
fn input(
program_id: &str,
payload: &[u8],
failed: bool,
path: &str,
) -> kb_store_core::CoreInstructionReplayInput {
let result = kb_store_core::CoreInstructionReplayInput::new(
format!("signature:{path}"),
"signature",
42,
path,
program_id,
failed,
if failed {
std::option::Option::Some(serde_json::json!({"InstructionError":[0,"Custom"]}))
} else {
std::option::Option::None
},
serde_json::json!([]),
serde_json::json!([]),
std::option::Option::Some(serde_json::json!({
"dataBase64": base64::engine::general_purpose::STANDARD.encode(payload)
})),
std::option::Option::None,
serde_json::json!([]),
serde_json::json!([]),
serde_json::json!([]),
serde_json::json!([]),
);
return match result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("registry replay input failed: {error}"),
};
}
#[test]
fn exact_program_boundary_and_interface_id_are_preserved() {
assert_eq!(
spl_elgamal_registry_interface::id().to_string(),
kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID
);
let decoder = crate::SplElgamalRegistryDecoder;
assert_eq!(kb_decoder_api::InstructionDecoder::coverage(&decoder).len(), 2);
let foreign = input(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, &[0, 1], false, "0");
assert_eq!(
kb_decoder_api::InstructionDecoder::decode(&decoder, &foreign).status,
kb_decoder_api::DecoderOutcomeStatus::Unsupported
);
}
#[test]
fn create_and_update_decode_exact_offsets_and_commit_state() {
for (tag, code, offset, failed, path) in [
(0_u8, "create_registry", 1_i8, false, "0"),
(1_u8, "update_registry", -1_i8, true, "1/0"),
(1_u8, "update_registry", 0_i8, false, "2"),
] {
let input = input(
kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID,
&[tag, offset as u8],
failed,
path,
);
let result = kb_decoder_api::InstructionDecoder::decode(
&crate::SplElgamalRegistryDecoder,
&input,
);
assert_eq!(result.status, kb_decoder_api::DecoderOutcomeStatus::Decoded);
assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some(code));
assert_eq!(
result.observations[0].payload_json["proofInstructionOffset"],
serde_json::json!(offset)
);
assert_eq!(result.observations[0].observation_committed, !failed);
}
}
#[test]
fn malformed_unknown_and_suffixed_wire_fail_closed() {
for payload in [std::vec::Vec::new(), vec![0], vec![2, 0], vec![0, 1, 2]] {
let input = input(
kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID,
payload.as_slice(),
false,
"0",
);
let result = kb_decoder_api::InstructionDecoder::decode(
&crate::SplElgamalRegistryDecoder,
&input,
);
assert_eq!(result.status, kb_decoder_api::DecoderOutcomeStatus::Failed);
assert!(result.observations.is_empty());
}
}
}

View File

@@ -0,0 +1,38 @@
// file: kb_decoder_spl_elgamal_registry/src/lib.rs
// version: 5
//! Decoder for the SPL Token-2022 ElGamal public-key registry program.
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
mod constants;
mod decoder;
mod registry;
pub mod state;
/// Crate-root access to `EVENT_VERSION` from `constants`.
pub(crate) use crate::constants::EVENT_VERSION;
/// Crate-root access to `MAX_INSTRUCTION_BYTES` from `constants`.
pub(crate) use crate::constants::MAX_INSTRUCTION_BYTES;
/// Crate-root access to `SURFACE_CODE` from `constants`.
pub(crate) use crate::constants::SURFACE_CODE;
/// Canonical tracing target for this crate.
pub(crate) use crate::constants::TRACING_TARGET;
/// Crate-root access to `ParsedRegistryInstruction` from `registry`.
pub(crate) use crate::registry::ParsedRegistryInstruction;
/// Crate-root access to `decode` from `registry`.
pub(crate) use crate::registry::decode;
/// Crate-root access to `decode_payload` from `registry`.
pub(crate) use crate::registry::decode_payload;
/// Crate-root access to `parse` from `registry`.
pub(crate) use crate::registry::parse;
/// Exact decoder for the SPL ElGamal registry program.
pub use crate::decoder::SplElgamalRegistryDecoder;
/// Exact byte length of one SPL ElGamal registry account.
pub use crate::state::ELGAMAL_REGISTRY_ACCOUNT_LEN;
/// Crate-root access to `ElGamalRegistryState` from `state`.
pub use crate::state::ElGamalRegistryState;
/// Parse one exact SPL ElGamal registry account.
pub use crate::state::parse_elgamal_registry_state;

View File

@@ -0,0 +1,191 @@
// file: kb_decoder_spl_elgamal_registry/src/registry.rs
// version: 3
//! Exact two-byte SPL ElGamal registry instruction decoding.
use base64::Engine; // rust-rules: trait-import
use sha2::Digest; // rust-rules: trait-import
#[derive(Clone, Debug)]
pub(crate) struct ParsedRegistryInstruction {
pub(crate) code: &'static str,
pub(crate) tag: u8,
pub(crate) proof_instruction_offset: i8,
}
pub(crate) fn decode_payload(
input: &kb_store_core::CoreInstructionReplayInput,
) -> std::result::Result<std::vec::Vec<u8>, std::string::String> {
let payload = match input.instruction_payload_json.as_ref() {
std::option::Option::Some(value) => value,
std::option::Option::None => {
return std::result::Result::Err(
"ElGamal registry instruction payload is not retained".to_string(),
);
},
};
let encoded = match payload.get("dataBase64").and_then(serde_json::Value::as_str) {
std::option::Option::Some(value) => value,
std::option::Option::None => {
return std::result::Result::Err(
"ElGamal registry payload does not contain dataBase64".to_string(),
);
},
};
if encoded.len() > 32 {
return std::result::Result::Err(
"ElGamal registry base64 payload is too large".to_string(),
);
}
let bytes = match base64::engine::general_purpose::STANDARD.decode(encoded.as_bytes()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(format!(
"ElGamal registry payload is not valid base64: {error}"
));
},
};
if bytes.len() > crate::MAX_INSTRUCTION_BYTES {
return std::result::Result::Err(format!(
"ElGamal registry payload exceeds {} bytes",
crate::MAX_INSTRUCTION_BYTES
));
}
return std::result::Result::Ok(bytes);
}
pub(crate) fn parse(
bytes: &[u8],
) -> std::result::Result<crate::ParsedRegistryInstruction, std::string::String> {
if bytes.len() != 2 {
return std::result::Result::Err(format!(
"ElGamal registry instruction requires exactly 2 bytes; received {}",
bytes.len()
));
}
let code = match bytes[0] {
0 => "create_registry",
1 => "update_registry",
tag => return std::result::Result::Err(format!("unknown ElGamal registry tag {tag}")),
};
return std::result::Result::Ok(crate::ParsedRegistryInstruction {
code,
tag: bytes[0],
proof_instruction_offset: bytes[1] as i8,
});
}
pub(crate) fn decode(
input: &kb_store_core::CoreInstructionReplayInput,
) -> kb_decoder_api::DecoderExecutionResult {
let bytes = match crate::decode_payload(input) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(message) => {
return kb_decoder_api::DecoderExecutionResult {
status: kb_decoder_api::DecoderOutcomeStatus::Failed,
recognized_entry_code: std::option::Option::None,
observations: std::vec::Vec::new(),
diagnostics: std::vec![kb_decoder_api::DecoderDiagnostic {
code: "elgamal_registry_payload_invalid".to_string(),
message,
retriable: false,
}],
};
},
};
let parsed = match crate::parse(bytes.as_slice()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(message) => {
return kb_decoder_api::DecoderExecutionResult {
status: kb_decoder_api::DecoderOutcomeStatus::Failed,
recognized_entry_code: bytes.first().and_then(|tag| {
return match tag {
0 => std::option::Option::Some("create_registry".to_string()),
1 => std::option::Option::Some("update_registry".to_string()),
_ => std::option::Option::None,
};
}),
observations: std::vec::Vec::new(),
diagnostics: std::vec![kb_decoder_api::DecoderDiagnostic {
code: "elgamal_registry_wire_invalid".to_string(),
message,
retriable: false,
}],
};
},
};
let committed = !input.transaction_failed;
let wire_hash = hash(bytes.as_slice());
let event = kb_model::DecodedProtocolEvent {
signature: kb_model::Signature(input.signature.clone()),
slot: kb_model::Slot(input.slot),
instruction_path: kb_model::InstructionPath(input.instruction_path.clone()),
program_id: kb_model::ProgramId(input.program_id.clone()),
protocol_code: kb_model::ProtocolCode(crate::SURFACE_CODE.to_string()),
surface_code: kb_model::SurfaceCode(crate::SURFACE_CODE.to_string()),
event_code: kb_model::EventCode(format!("{}.{}", crate::SURFACE_CODE, parsed.code)),
event_name: kb_model::EventName(parsed.code.to_string()),
event_family: kb_model::EventFamily::Admin,
source_kind: if input.instruction_path.contains('/') {
kb_model::EventSourceKind::InnerInstruction
} else {
kb_model::EventSourceKind::Instruction
},
confidence: kb_model::DecoderConfidence::ManualExact,
};
let observation = kb_decoder_api::DecodedObservation {
event_key: format!("elgamal_registry:{}:0", parsed.code),
event,
payload_json: serde_json::json!({
"eventVersion": crate::EVENT_VERSION,
"instruction": parsed.code,
"wireTag": parsed.tag,
"proofInstructionOffset": parsed.proof_instruction_offset,
"proofLocationKind": if parsed.proof_instruction_offset == 0 { "context_state_account" } else { "relative_instruction_offset" },
"instructionPath": input.instruction_path,
"instructionLocation": if input.instruction_path.contains('/') { "inner" } else { "outer" },
"transactionSucceeded": !input.transaction_failed,
"committed": committed,
"accounts": input.instruction_accounts_json,
"wire": {
"lengthBytes": bytes.len(),
"sha256": wire_hash,
"prefixHex": hex(bytes.as_slice()),
"complete": true,
},
"programBoundary": {
"registryProgramId": kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID,
"token2022ProgramId": kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID,
"zkProofProgramId": kb_program_ids::ZK_ELGAMAL_PROOF_PROGRAM_ID,
"proofDecodedHere": false,
}
}),
transaction_failed: input.transaction_failed,
transaction_error: input.transaction_err_json.clone(),
observation_committed: committed,
proof: kb_decoder_api::DecoderProof {
kind: kb_decoder_api::DecoderProofKind::Manual,
confidence: kb_model::DecoderConfidence::ManualExact,
evidence: std::vec![
"spl_elgamal_registry_interface_0_2_1_registry_instruction_unpack".to_string(),
format!("wire_tag:{}", parsed.tag),
format!("wire_sha256:{wire_hash}"),
],
},
};
return kb_decoder_api::DecoderExecutionResult {
status: kb_decoder_api::DecoderOutcomeStatus::Decoded,
recognized_entry_code: std::option::Option::Some(parsed.code.to_string()),
observations: std::vec![observation],
diagnostics: std::vec::Vec::new(),
};
}
fn hash(bytes: &[u8]) -> std::string::String {
let digest = sha2::Sha256::digest(bytes);
return digest.iter().map(|byte| return format!("{byte:02x}")).collect();
}
fn hex(bytes: &[u8]) -> std::string::String {
return bytes.iter().map(|byte| return format!("{byte:02x}")).collect();
}

View File

@@ -0,0 +1,76 @@
// file: kb_decoder_spl_elgamal_registry/src/state.rs
// version: 2
//! Strict SPL ElGamal registry account-state parsing.
use base64::Engine; // rust-rules: trait-import
/// Exact byte length of one SPL ElGamal registry account.
pub const ELGAMAL_REGISTRY_ACCOUNT_LEN: usize = 64;
/// Public state retained by one SPL ElGamal registry account.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ElGamalRegistryState {
/// Wallet address associated with this registry.
pub owner: String,
/// Exact 32-byte ElGamal public key encoded as standard base64.
pub elgamal_pubkey_base64: String,
/// Exact account bytes encoded as lowercase hexadecimal.
pub wire_hex: String,
}
/// Parse one exact SPL ElGamal registry account.
pub fn parse_elgamal_registry_state(
data: &[u8],
) -> std::result::Result<ElGamalRegistryState, std::string::String> {
if data.len() != ELGAMAL_REGISTRY_ACCOUNT_LEN {
return std::result::Result::Err(format!(
"SPL ElGamal registry account requires exactly {ELGAMAL_REGISTRY_ACCOUNT_LEN} bytes; received {}",
data.len()
));
}
return std::result::Result::Ok(ElGamalRegistryState {
owner: bs58::encode(&data[..32]).into_string(),
elgamal_pubkey_base64: base64::engine::general_purpose::STANDARD.encode(&data[32..64]),
wire_hex: lower_hex(data),
});
}
fn lower_hex(bytes: &[u8]) -> String {
let mut output = String::with_capacity(bytes.len() * 2);
for byte in bytes {
output.push_str(&format!("{byte:02x}"));
}
return output;
}
#[cfg(test)]
mod tests {
use base64::Engine; // rust-rules: trait-import
#[test]
fn exact_registry_state_preserves_owner_key_and_wire() {
let mut data = [0u8; crate::ELGAMAL_REGISTRY_ACCOUNT_LEN];
data[..32].fill(7);
data[32..].fill(9);
let parsed = crate::parse_elgamal_registry_state(&data);
assert_eq!(
parsed.as_ref().map(|state| return state.owner.clone()),
std::result::Result::Ok(bs58::encode([7u8; 32]).into_string())
);
assert_eq!(
parsed.as_ref().map(|state| return state.elgamal_pubkey_base64.clone()),
std::result::Result::Ok(base64::engine::general_purpose::STANDARD.encode([9u8; 32]))
);
assert_eq!(
parsed.as_ref().map(|state| return state.wire_hex.len()),
std::result::Result::Ok(128)
);
}
#[test]
fn registry_state_rejects_every_non_exact_length() {
assert!(crate::parse_elgamal_registry_state(&[0; 63]).is_err());
assert!(crate::parse_elgamal_registry_state(&[0; 65]).is_err());
}
}