5
5
lazy_static:: lazy_static,
6
6
solana_sdk:: {
7
7
address_lookup_table, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
8
- compute_budget, ed25519_program, loader_v4, pubkey:: Pubkey , secp256k1_program,
8
+ compute_budget, ed25519_program,
9
+ feature_set:: { self , FeatureSet } ,
10
+ loader_v4,
11
+ pubkey:: Pubkey ,
12
+ secp256k1_program,
9
13
} ,
10
14
} ;
11
15
12
- // Number of compute units for each built-in programs
16
+ /// DEVELOPER: when a builtin is migrated to sbpf, please add its corresponding
17
+ /// migration feature ID to BUILTIN_INSTRUCTION_COSTS, so the builtin's default
18
+ /// cost can be determined properly based on feature status.
19
+ /// When migration completed, eg the feature gate is enabled everywhere, please
20
+ /// remove that builtin entry from BUILTIN_INSTRUCTION_COSTS.
21
+ #[ derive( Clone ) ]
22
+ struct BuiltinCost {
23
+ native_cost : u64 ,
24
+ core_bpf_migration_feature : Option < Pubkey > ,
25
+ }
26
+
13
27
lazy_static ! {
14
28
/// Number of compute units for each built-in programs
15
29
///
@@ -20,21 +34,95 @@ lazy_static! {
20
34
/// calculate the cost of a transaction which is used in replay to enforce
21
35
/// block cost limits as of
22
36
/// https://github.com/solana-labs/solana/issues/29595.
23
- pub static ref BUILTIN_INSTRUCTION_COSTS : AHashMap <Pubkey , u64 > = [
24
- ( solana_stake_program:: id( ) , solana_stake_program:: stake_instruction:: DEFAULT_COMPUTE_UNITS ) ,
25
- ( solana_config_program:: id( ) , solana_config_program:: config_processor:: DEFAULT_COMPUTE_UNITS ) ,
26
- ( solana_vote_program:: id( ) , solana_vote_program:: vote_processor:: DEFAULT_COMPUTE_UNITS ) ,
27
- ( solana_system_program:: id( ) , solana_system_program:: system_processor:: DEFAULT_COMPUTE_UNITS ) ,
28
- ( compute_budget:: id( ) , solana_compute_budget_program:: DEFAULT_COMPUTE_UNITS ) ,
29
- ( address_lookup_table:: program:: id( ) , solana_address_lookup_table_program:: processor:: DEFAULT_COMPUTE_UNITS ) ,
30
- ( bpf_loader_upgradeable:: id( ) , solana_bpf_loader_program:: UPGRADEABLE_LOADER_COMPUTE_UNITS ) ,
31
- ( bpf_loader_deprecated:: id( ) , solana_bpf_loader_program:: DEPRECATED_LOADER_COMPUTE_UNITS ) ,
32
- ( bpf_loader:: id( ) , solana_bpf_loader_program:: DEFAULT_LOADER_COMPUTE_UNITS ) ,
33
- ( loader_v4:: id( ) , solana_loader_v4_program:: DEFAULT_COMPUTE_UNITS ) ,
34
- // Note: These are precompile, run directly in bank during sanitizing;
35
- ( secp256k1_program:: id( ) , 0 ) ,
36
- ( ed25519_program:: id( ) , 0 ) ,
37
- // DO NOT ADD MORE ENTRIES TO THIS MAP
37
+ static ref BUILTIN_INSTRUCTION_COSTS : AHashMap <Pubkey , BuiltinCost > = [
38
+ (
39
+ solana_stake_program:: id( ) ,
40
+ BuiltinCost {
41
+ native_cost: solana_stake_program:: stake_instruction:: DEFAULT_COMPUTE_UNITS ,
42
+ core_bpf_migration_feature: Some ( feature_set:: migrate_stake_program_to_core_bpf:: id( ) ) ,
43
+ } ,
44
+ ) ,
45
+ (
46
+ solana_config_program:: id( ) ,
47
+ BuiltinCost {
48
+ native_cost: solana_config_program:: config_processor:: DEFAULT_COMPUTE_UNITS ,
49
+ core_bpf_migration_feature: Some ( feature_set:: migrate_config_program_to_core_bpf:: id( ) ) ,
50
+ } ,
51
+ ) ,
52
+ (
53
+ solana_vote_program:: id( ) ,
54
+ BuiltinCost {
55
+ native_cost: solana_vote_program:: vote_processor:: DEFAULT_COMPUTE_UNITS ,
56
+ core_bpf_migration_feature: None ,
57
+ } ,
58
+ ) ,
59
+ (
60
+ solana_system_program:: id( ) ,
61
+ BuiltinCost {
62
+ native_cost: solana_system_program:: system_processor:: DEFAULT_COMPUTE_UNITS ,
63
+ core_bpf_migration_feature: None ,
64
+ } ,
65
+ ) ,
66
+ (
67
+ compute_budget:: id( ) ,
68
+ BuiltinCost {
69
+ native_cost: solana_compute_budget_program:: DEFAULT_COMPUTE_UNITS ,
70
+ core_bpf_migration_feature: None ,
71
+ } ,
72
+ ) ,
73
+ (
74
+ address_lookup_table:: program:: id( ) ,
75
+ BuiltinCost {
76
+ native_cost: solana_address_lookup_table_program:: processor:: DEFAULT_COMPUTE_UNITS ,
77
+ core_bpf_migration_feature: Some (
78
+ feature_set:: migrate_address_lookup_table_program_to_core_bpf:: id( ) ,
79
+ ) ,
80
+ } ,
81
+ ) ,
82
+ (
83
+ bpf_loader_upgradeable:: id( ) ,
84
+ BuiltinCost {
85
+ native_cost: solana_bpf_loader_program:: UPGRADEABLE_LOADER_COMPUTE_UNITS ,
86
+ core_bpf_migration_feature: None ,
87
+ } ,
88
+ ) ,
89
+ (
90
+ bpf_loader_deprecated:: id( ) ,
91
+ BuiltinCost {
92
+ native_cost: solana_bpf_loader_program:: DEPRECATED_LOADER_COMPUTE_UNITS ,
93
+ core_bpf_migration_feature: None ,
94
+ } ,
95
+ ) ,
96
+ (
97
+ bpf_loader:: id( ) ,
98
+ BuiltinCost {
99
+ native_cost: solana_bpf_loader_program:: DEFAULT_LOADER_COMPUTE_UNITS ,
100
+ core_bpf_migration_feature: None ,
101
+ } ,
102
+ ) ,
103
+ (
104
+ loader_v4:: id( ) ,
105
+ BuiltinCost {
106
+ native_cost: solana_loader_v4_program:: DEFAULT_COMPUTE_UNITS ,
107
+ core_bpf_migration_feature: None ,
108
+ } ,
109
+ ) ,
110
+ // Note: These are precompile, run directly in bank during sanitizing;
111
+ (
112
+ secp256k1_program:: id( ) ,
113
+ BuiltinCost {
114
+ native_cost: 0 ,
115
+ core_bpf_migration_feature: None ,
116
+ } ,
117
+ ) ,
118
+ (
119
+ ed25519_program:: id( ) ,
120
+ BuiltinCost {
121
+ native_cost: 0 ,
122
+ core_bpf_migration_feature: None ,
123
+ } ,
124
+ ) ,
125
+ // DO NOT ADD MORE ENTRIES TO THIS MAP
38
126
]
39
127
. iter( )
40
128
. cloned( )
@@ -54,3 +142,58 @@ lazy_static! {
54
142
temp_table
55
143
} ;
56
144
}
145
+
146
+ pub fn get_builtin_instruction_cost < ' a > (
147
+ program_id : & ' a Pubkey ,
148
+ feature_set : & ' a FeatureSet ,
149
+ ) -> Option < u64 > {
150
+ BUILTIN_INSTRUCTION_COSTS
151
+ . get ( program_id)
152
+ . filter (
153
+ // Returns true if builtin program id has no core_bpf_migration_feature or feature is not activated;
154
+ // otherwise returns false because it's not considered as builtin
155
+ |builtin_cost| -> bool {
156
+ builtin_cost
157
+ . core_bpf_migration_feature
158
+ . map ( |feature_id| !feature_set. is_active ( & feature_id) )
159
+ . unwrap_or ( true )
160
+ } ,
161
+ )
162
+ . map ( |builtin_cost| builtin_cost. native_cost )
163
+ }
164
+
165
+ #[ cfg( test) ]
166
+ mod test {
167
+ use super :: * ;
168
+
169
+ #[ test]
170
+ fn test_get_builtin_instruction_cost ( ) {
171
+ // use native cost if no migration planned
172
+ assert_eq ! (
173
+ Some ( solana_compute_budget_program:: DEFAULT_COMPUTE_UNITS ) ,
174
+ get_builtin_instruction_cost( & compute_budget:: id( ) , & FeatureSet :: all_enabled( ) )
175
+ ) ;
176
+
177
+ // use native cost if migration is planned but not activated
178
+ assert_eq ! (
179
+ Some ( solana_stake_program:: stake_instruction:: DEFAULT_COMPUTE_UNITS ) ,
180
+ get_builtin_instruction_cost( & solana_stake_program:: id( ) , & FeatureSet :: default ( ) )
181
+ ) ;
182
+
183
+ // None if migration is planned and activated, in which case, it's no longer builtin
184
+ assert ! ( get_builtin_instruction_cost(
185
+ & solana_stake_program:: id( ) ,
186
+ & FeatureSet :: all_enabled( )
187
+ )
188
+ . is_none( ) ) ;
189
+
190
+ // None if not builtin
191
+ assert ! (
192
+ get_builtin_instruction_cost( & Pubkey :: new_unique( ) , & FeatureSet :: default ( ) ) . is_none( )
193
+ ) ;
194
+ assert ! (
195
+ get_builtin_instruction_cost( & Pubkey :: new_unique( ) , & FeatureSet :: all_enabled( ) )
196
+ . is_none( )
197
+ ) ;
198
+ }
199
+ }
0 commit comments