solana_precompiles/
lib.rs

1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2use {
3    lazy_static::lazy_static, solana_feature_set::FeatureSet,
4    solana_message::compiled_instruction::CompiledInstruction,
5    solana_precompile_error::PrecompileError, solana_pubkey::Pubkey,
6};
7
8/// All precompiled programs must implement the `Verify` function
9pub type Verify = fn(&[u8], &[&[u8]], &FeatureSet) -> std::result::Result<(), PrecompileError>;
10
11/// Information on a precompiled program
12pub struct Precompile {
13    /// Program id
14    pub program_id: Pubkey,
15    /// Feature to enable on, `None` indicates always enabled
16    pub feature: Option<Pubkey>,
17    /// Verification function
18    pub verify_fn: Verify,
19}
20impl Precompile {
21    /// Creates a new `Precompile`
22    pub fn new(program_id: Pubkey, feature: Option<Pubkey>, verify_fn: Verify) -> Self {
23        Precompile {
24            program_id,
25            feature,
26            verify_fn,
27        }
28    }
29    /// Check if a program id is this precompiled program
30    pub fn check_id<F>(&self, program_id: &Pubkey, is_enabled: F) -> bool
31    where
32        F: Fn(&Pubkey) -> bool,
33    {
34        self.feature
35            .map_or(true, |ref feature_id| is_enabled(feature_id))
36            && self.program_id == *program_id
37    }
38    /// Verify this precompiled program
39    pub fn verify(
40        &self,
41        data: &[u8],
42        instruction_datas: &[&[u8]],
43        feature_set: &FeatureSet,
44    ) -> std::result::Result<(), PrecompileError> {
45        (self.verify_fn)(data, instruction_datas, feature_set)
46    }
47}
48
49lazy_static! {
50    /// The list of all precompiled programs
51    static ref PRECOMPILES: Vec<Precompile> = vec![
52        Precompile::new(
53            solana_sdk_ids::secp256k1_program::id(),
54            None, // always enabled
55            solana_secp256k1_program::verify,
56        ),
57        Precompile::new(
58            solana_sdk_ids::ed25519_program::id(),
59            None, // always enabled
60            solana_ed25519_program::verify,
61        ),
62        Precompile::new(
63            solana_sdk_ids::secp256r1_program::id(),
64            Some(solana_feature_set::enable_secp256r1_precompile::id()),
65            solana_secp256r1_program::verify,
66        )
67    ];
68}
69
70/// Check if a program is a precompiled program
71pub fn is_precompile<F>(program_id: &Pubkey, is_enabled: F) -> bool
72where
73    F: Fn(&Pubkey) -> bool,
74{
75    PRECOMPILES
76        .iter()
77        .any(|precompile| precompile.check_id(program_id, |feature_id| is_enabled(feature_id)))
78}
79
80/// Find an enabled precompiled program
81pub fn get_precompile<F>(program_id: &Pubkey, is_enabled: F) -> Option<&Precompile>
82where
83    F: Fn(&Pubkey) -> bool,
84{
85    PRECOMPILES
86        .iter()
87        .find(|precompile| precompile.check_id(program_id, |feature_id| is_enabled(feature_id)))
88}
89
90pub fn get_precompiles<'a>() -> &'a [Precompile] {
91    &PRECOMPILES
92}
93
94/// Check that a program is precompiled and if so verify it
95pub fn verify_if_precompile(
96    program_id: &Pubkey,
97    precompile_instruction: &CompiledInstruction,
98    all_instructions: &[CompiledInstruction],
99    feature_set: &FeatureSet,
100) -> Result<(), PrecompileError> {
101    for precompile in PRECOMPILES.iter() {
102        if precompile.check_id(program_id, |feature_id| feature_set.is_active(feature_id)) {
103            let instruction_datas: Vec<_> = all_instructions
104                .iter()
105                .map(|instruction| instruction.data.as_ref())
106                .collect();
107            return precompile.verify(
108                &precompile_instruction.data,
109                &instruction_datas,
110                feature_set,
111            );
112        }
113    }
114    Ok(())
115}