solana_precompiles/
lib.rs

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