clone_solana_precompiles/
lib.rs1#![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
9pub type Verify = fn(&[u8], &[&[u8]], &FeatureSet) -> std::result::Result<(), PrecompileError>;
11
12pub struct Precompile {
14 pub program_id: Pubkey,
16 pub feature: Option<Pubkey>,
18 pub verify_fn: Verify,
20}
21impl Precompile {
22 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 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 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 static ref PRECOMPILES: Vec<Precompile> = vec![
53 Precompile::new(
54 clone_solana_sdk_ids::secp256k1_program::id(),
55 None, clone_solana_secp256k1_program::verify,
57 ),
58 Precompile::new(
59 clone_solana_sdk_ids::ed25519_program::id(),
60 None, 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
71pub 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
81pub 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
95pub 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}