clone_solana_precompiles/
lib.rs

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