solana_sdk/
precompiles.rs

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