solana_sdk/
precompiles.rs1#![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
13pub type Verify = fn(&[u8], &[&[u8]], &FeatureSet) -> std::result::Result<(), PrecompileError>;
15
16pub struct Precompile {
18 pub program_id: Pubkey,
20 pub feature: Option<Pubkey>,
22 pub verify_fn: Verify,
24}
25impl Precompile {
26 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 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 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 static ref PRECOMPILES: Vec<Precompile> = vec![
57 Precompile::new(
58 crate::secp256k1_program::id(),
59 None, crate::secp256k1_instruction::verify,
61 ),
62 Precompile::new(
63 crate::ed25519_program::id(),
64 None, 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
75pub 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
85pub 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
99pub 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}