rialo-s-precompiles 0.12.2

Solana precompiled programs.
#![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;

/// All precompiled programs must implement the `Verify` function.
///
/// Rialo ships every precompile as part of its genesis ABI — none of them
/// gate on a feature id — so the verifier does not receive a `FeatureSet`.
pub type Verify = fn(&[u8], &[&[u8]]) -> std::result::Result<(), PrecompileError>;

/// Information on a precompiled program.
pub struct Precompile {
    /// Program id
    pub program_id: Pubkey,
    /// Verification function
    pub verify_fn: Verify,
}
impl Precompile {
    /// Creates a new `Precompile`.
    pub fn new(program_id: Pubkey, verify_fn: Verify) -> Self {
        Precompile {
            program_id,
            verify_fn,
        }
    }
    /// Check if a program id is this precompiled program.
    pub fn check_id(&self, program_id: &Pubkey) -> bool {
        self.program_id == *program_id
    }
    /// Verify this precompiled program.
    pub fn verify(
        &self,
        data: &[u8],
        instruction_datas: &[&[u8]],
    ) -> std::result::Result<(), PrecompileError> {
        (self.verify_fn)(data, instruction_datas)
    }
}

/// The list of all precompiled programs. Every Rialo precompile is part of
/// the genesis ABI; none of them gate on a feature id.
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,
        ),
    ]
});

/// Check if a program is a precompiled program.
pub fn is_precompile(program_id: &Pubkey) -> bool {
    PRECOMPILES
        .iter()
        .any(|precompile| precompile.check_id(program_id))
}

/// Find a precompiled program.
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
}

/// Check that a program is precompiled and if so verify it.
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(())
}