solana_precompiles/
lib.rs1#![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
8pub type Verify = fn(&[u8], &[&[u8]], &FeatureSet) -> std::result::Result<(), PrecompileError>;
10
11pub struct Precompile {
13 pub program_id: Pubkey,
15 pub feature: Option<Pubkey>,
17 pub verify_fn: Verify,
19}
20impl Precompile {
21 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 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 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 static ref PRECOMPILES: Vec<Precompile> = vec![
52 Precompile::new(
53 solana_sdk_ids::secp256k1_program::id(),
54 None, solana_secp256k1_program::verify,
56 ),
57 Precompile::new(
58 solana_sdk_ids::ed25519_program::id(),
59 None, 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
70pub 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
80pub 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
94pub 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}