88 solana_loader_v3_interface:: state:: UpgradeableLoaderState ,
99 solana_loader_v4_interface:: state:: { LoaderV4State , LoaderV4Status } ,
1010 solana_program_runtime:: {
11- invoke_context:: BuiltinFunctionWithContext ,
11+ invoke_context:: { BuiltinFunctionWithContext , InvokeContext } ,
1212 loaded_programs:: { LoadProgramMetrics , ProgramCacheEntry , ProgramCacheForTxBatch } ,
13+ solana_sbpf:: {
14+ elf:: ElfError ,
15+ program:: { BuiltinFunction , BuiltinProgram } ,
16+ } ,
1317 } ,
1418 solana_pubkey:: Pubkey ,
1519 solana_rent:: Rent ,
@@ -57,13 +61,23 @@ pub struct ProgramCache {
5761 //
5862 // K: program ID, V: loader key
5963 entries_cache : Rc < RefCell < HashMap < Pubkey , Pubkey > > > ,
64+ // The function registry (syscalls) to use for verifying and loading
65+ // program ELFs.
66+ program_runtime_environment : BuiltinProgram < InvokeContext < ' static > > ,
6067}
6168
62- impl Default for ProgramCache {
63- fn default ( ) -> Self {
69+ impl ProgramCache {
70+ pub fn new ( feature_set : & FeatureSet , compute_budget : & ComputeBudget ) -> Self {
6471 let me = Self {
6572 cache : Rc :: new ( RefCell :: new ( ProgramCacheForTxBatch :: default ( ) ) ) ,
6673 entries_cache : Rc :: new ( RefCell :: new ( HashMap :: new ( ) ) ) ,
74+ program_runtime_environment : create_program_runtime_environment_v1 (
75+ feature_set,
76+ compute_budget,
77+ /* reject_deployment_of_broken_elfs */ false ,
78+ /* debugging_features */ false ,
79+ )
80+ . unwrap ( ) ,
6781 } ;
6882 BUILTINS . iter ( ) . for_each ( |builtin| {
6983 let program_id = builtin. program_id ;
@@ -72,9 +86,7 @@ impl Default for ProgramCache {
7286 } ) ;
7387 me
7488 }
75- }
7689
77- impl ProgramCache {
7890 pub ( crate ) fn cache ( & self ) -> RefMut < ProgramCacheForTxBatch > {
7991 self . cache . borrow_mut ( )
8092 }
@@ -94,18 +106,24 @@ impl ProgramCache {
94106 }
95107
96108 /// Add a program to the cache.
97- pub fn add_program (
98- & mut self ,
99- program_id : & Pubkey ,
100- loader_key : & Pubkey ,
101- elf : & [ u8 ] ,
102- compute_budget : & ComputeBudget ,
103- feature_set : & FeatureSet ,
104- ) {
105- let environment = Arc :: new (
106- create_program_runtime_environment_v1 ( feature_set, compute_budget, false , false )
107- . unwrap ( ) ,
108- ) ;
109+ pub fn add_program ( & mut self , program_id : & Pubkey , loader_key : & Pubkey , elf : & [ u8 ] ) {
110+ // This might look rough, but it's actually functionally the same as
111+ // calling `create_program_runtime_environment_v1` on every addition.
112+ let environment = {
113+ let config = self . program_runtime_environment . get_config ( ) . clone ( ) ;
114+ let mut loader = BuiltinProgram :: new_loader ( config) ;
115+
116+ for ( _key, ( name, value) ) in self
117+ . program_runtime_environment
118+ . get_function_registry ( )
119+ . iter ( )
120+ {
121+ let name = std:: str:: from_utf8 ( name) . unwrap ( ) ;
122+ loader. register_function ( name, value) . unwrap ( ) ;
123+ }
124+
125+ Arc :: new ( loader)
126+ } ;
109127 self . replenish (
110128 * program_id,
111129 Arc :: new (
@@ -149,6 +167,19 @@ impl ProgramCache {
149167 } )
150168 . collect ( )
151169 }
170+
171+ /// Register a new function (syscall) with the program runtime environment.
172+ ///
173+ /// **Important**: You should register all custom syscalls BEFORE adding any
174+ /// programs to the store that will use them.
175+ pub fn register_function (
176+ & mut self ,
177+ name : & str ,
178+ value : BuiltinFunction < InvokeContext < ' static > > ,
179+ ) -> Result < ( ) , ElfError > {
180+ self . program_runtime_environment
181+ . register_function ( name, value)
182+ }
152183}
153184
154185pub struct Builtin {
0 commit comments