#![cfg_attr(docsrs, feature(doc_auto_cfg))]
use std::sync::LazyLock;
use rialo_s_message::compiled_instruction::CompiledInstruction;
use rialo_s_precompile_error::PrecompileError;
use rialo_s_pubkey::Pubkey;
pub type Verify = fn(&[u8], &[&[u8]]) -> std::result::Result<(), PrecompileError>;
pub struct Precompile {
pub program_id: Pubkey,
pub verify_fn: Verify,
}
impl Precompile {
pub fn new(program_id: Pubkey, verify_fn: Verify) -> Self {
Precompile {
program_id,
verify_fn,
}
}
pub fn check_id(&self, program_id: &Pubkey) -> bool {
self.program_id == *program_id
}
pub fn verify(
&self,
data: &[u8],
instruction_datas: &[&[u8]],
) -> std::result::Result<(), PrecompileError> {
(self.verify_fn)(data, instruction_datas)
}
}
static PRECOMPILES: LazyLock<Vec<Precompile>> = LazyLock::new(|| {
vec![
Precompile::new(
rialo_s_sdk_ids::secp256k1_program::id(),
rialo_s_secp256k1_program::verify,
),
Precompile::new(
rialo_s_sdk_ids::ed25519_program::id(),
rialo_s_ed25519_program::verify,
),
Precompile::new(
rialo_s_sdk_ids::secp256r1_program::id(),
rialo_s_secp256r1_program::verify,
),
]
});
pub fn is_precompile(program_id: &Pubkey) -> bool {
PRECOMPILES
.iter()
.any(|precompile| precompile.check_id(program_id))
}
pub fn get_precompile(program_id: &Pubkey) -> Option<&Precompile> {
PRECOMPILES
.iter()
.find(|precompile| precompile.check_id(program_id))
}
pub fn get_precompiles<'a>() -> &'a [Precompile] {
&PRECOMPILES
}
pub fn verify_if_precompile(
program_id: &Pubkey,
precompile_instruction: &CompiledInstruction,
all_instructions: &[CompiledInstruction],
) -> Result<(), PrecompileError> {
for precompile in PRECOMPILES.iter() {
if precompile.check_id(program_id) {
let instruction_datas: Vec<_> = all_instructions
.iter()
.map(|instruction| instruction.data.as_ref())
.collect();
return precompile.verify(&precompile_instruction.data, &instruction_datas);
}
}
Ok(())
}