solana_builtins/
lib.rs

1//! Solana builtin programs.
2//!
3//! Warning: This crate is not for public consumption. It will change, and
4//! could possibly be removed altogether in the future. For now, it is purely
5//! for the purpose of managing the migration of builtins to Core BPF.
6//!
7//! It serves as a source of truth for:
8//! * The list of builtins that a Bank should add.
9//! * Which of those builtins have been assigned a feature gate to migrate to
10//!   Core BPF, as well as whether or not that feature gate has been activated.
11
12pub mod core_bpf_migration;
13pub mod prototype;
14
15use {
16    crate::{
17        core_bpf_migration::{CoreBpfMigrationConfig, CoreBpfMigrationTargetType},
18        prototype::{BuiltinPrototype, StatelessBuiltinPrototype},
19    },
20    agave_feature_set as feature_set,
21    solana_sdk_ids::{bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable},
22};
23
24macro_rules! testable_prototype {
25    ($prototype:ident {
26        core_bpf_migration_config: $core_bpf_migration_config:expr,
27        name: $name:ident,
28        $($field:ident : $value:expr),* $(,)?
29    }) => {
30        $prototype {
31            core_bpf_migration_config: {
32                #[cfg(not(feature = "dev-context-only-utils"))]
33                {
34                    $core_bpf_migration_config
35                }
36                #[cfg(feature = "dev-context-only-utils")]
37                {
38                    Some( test_only::$name::CONFIG )
39                }
40            },
41            name: stringify!($name),
42            $($field: $value),*
43        }
44    };
45}
46
47/// DEVELOPER: when a builtin is migrated to sbpf, please add its corresponding
48/// migration feature ID to solana-builtin-default-costs::BUILTIN_INSTRUCTION_COSTS,
49/// so the builtin's default cost can be determined properly based on feature status.
50/// When migration completed, and the feature gate is enabled everywhere, please
51/// remove that builtin entry from solana-builtin-default-costs::BUILTIN_INSTRUCTION_COSTS.
52pub static BUILTINS: &[BuiltinPrototype] = &[
53    testable_prototype!(BuiltinPrototype {
54        core_bpf_migration_config: None,
55        name: system_program,
56        enable_feature_id: None,
57        program_id: solana_system_program::id(),
58        entrypoint: solana_system_program::system_processor::Entrypoint::vm,
59    }),
60    testable_prototype!(BuiltinPrototype {
61        core_bpf_migration_config: None,
62        name: vote_program,
63        enable_feature_id: None,
64        program_id: solana_vote_program::id(),
65        entrypoint: solana_vote_program::vote_processor::Entrypoint::vm,
66    }),
67    BuiltinPrototype {
68        core_bpf_migration_config: Some(CoreBpfMigrationConfig {
69            source_buffer_address: buffer_accounts::stake_program::id(),
70            upgrade_authority_address: None,
71            feature_id: agave_feature_set::migrate_stake_program_to_core_bpf::id(),
72            verified_build_hash: None,
73            migration_target: CoreBpfMigrationTargetType::Builtin,
74            datapoint_name: "migrate_builtin_to_core_bpf_stake_program",
75        }),
76        name: "stake_program",
77        enable_feature_id: None,
78        program_id: solana_stake_program::id(),
79        entrypoint: solana_stake_program::stake_instruction::Entrypoint::vm,
80    },
81    testable_prototype!(BuiltinPrototype {
82        core_bpf_migration_config: None,
83        name: solana_bpf_loader_deprecated_program,
84        enable_feature_id: None,
85        program_id: bpf_loader_deprecated::id(),
86        entrypoint: solana_bpf_loader_program::Entrypoint::vm,
87    }),
88    testable_prototype!(BuiltinPrototype {
89        core_bpf_migration_config: None,
90        name: solana_bpf_loader_program,
91        enable_feature_id: None,
92        program_id: bpf_loader::id(),
93        entrypoint: solana_bpf_loader_program::Entrypoint::vm,
94    }),
95    testable_prototype!(BuiltinPrototype {
96        core_bpf_migration_config: None,
97        name: solana_bpf_loader_upgradeable_program,
98        enable_feature_id: None,
99        program_id: bpf_loader_upgradeable::id(),
100        entrypoint: solana_bpf_loader_program::Entrypoint::vm,
101    }),
102    testable_prototype!(BuiltinPrototype {
103        core_bpf_migration_config: None,
104        name: compute_budget_program,
105        enable_feature_id: None,
106        program_id: solana_sdk_ids::compute_budget::id(),
107        entrypoint: solana_compute_budget_program::Entrypoint::vm,
108    }),
109    testable_prototype!(BuiltinPrototype {
110        core_bpf_migration_config: None,
111        name: zk_token_proof_program,
112        enable_feature_id: Some(feature_set::zk_token_sdk_enabled::id()),
113        program_id: solana_sdk_ids::zk_token_proof_program::id(),
114        entrypoint: solana_zk_token_proof_program::Entrypoint::vm,
115    }),
116    testable_prototype!(BuiltinPrototype {
117        core_bpf_migration_config: None,
118        name: loader_v4,
119        enable_feature_id: Some(feature_set::enable_loader_v4::id()),
120        program_id: solana_sdk_ids::loader_v4::id(),
121        entrypoint: solana_loader_v4_program::Entrypoint::vm,
122    }),
123    testable_prototype!(BuiltinPrototype {
124        core_bpf_migration_config: None,
125        name: zk_elgamal_proof_program,
126        enable_feature_id: Some(feature_set::zk_elgamal_proof_program_enabled::id()),
127        program_id: solana_sdk_ids::zk_elgamal_proof_program::id(),
128        entrypoint: solana_zk_elgamal_proof_program::Entrypoint::vm,
129    }),
130];
131
132pub static STATELESS_BUILTINS: &[StatelessBuiltinPrototype] = &[StatelessBuiltinPrototype {
133    core_bpf_migration_config: Some(CoreBpfMigrationConfig {
134        source_buffer_address: buffer_accounts::slashing_program::id(),
135        upgrade_authority_address: None,
136        feature_id: feature_set::enshrine_slashing_program::id(),
137        verified_build_hash: Some(buffer_accounts::slashing_program::VERIFIED_BUILD_HASH),
138        migration_target: CoreBpfMigrationTargetType::Stateless,
139        datapoint_name: "enshrine_slashing_program",
140    }),
141    program_id: buffer_accounts::slashing_program::PROGRAM_ID,
142    name: "solana_slashing_program",
143}];
144
145/// Live source buffer accounts for builtin migrations.
146mod buffer_accounts {
147    pub mod stake_program {
148        solana_pubkey::declare_id!("8t3vv6v99tQA6Gp7fVdsBH66hQMaswH5qsJVqJqo8xvG");
149    }
150    pub mod slashing_program {
151        use {solana_hash::Hash, solana_pubkey::Pubkey};
152
153        solana_pubkey::declare_id!("S1asHs4je6wPb2kWiHqNNdpNRiDaBEDQyfyCThhsrgv");
154
155        pub(crate) const PROGRAM_ID: Pubkey =
156            Pubkey::from_str_const("S1ashing11111111111111111111111111111111111");
157        // 192ed727334abe822d5accba8b886e25f88b03c76973c2e7290cfb55b9e1115f
158        const HASH_BYTES: [u8; 32] = [
159            0x19, 0x2e, 0xd7, 0x27, 0x33, 0x4a, 0xbe, 0x82, 0x2d, 0x5a, 0xcc, 0xba, 0x8b, 0x88,
160            0x6e, 0x25, 0xf8, 0x8b, 0x03, 0xc7, 0x69, 0x73, 0xc2, 0xe7, 0x29, 0x0c, 0xfb, 0x55,
161            0xb9, 0xe1, 0x11, 0x5f,
162        ];
163        pub(crate) const VERIFIED_BUILD_HASH: Hash = Hash::new_from_array(HASH_BYTES);
164    }
165}
166
167// This module contains a number of arbitrary addresses used for testing Core
168// BPF migrations.
169// Since the list of builtins is static, using `declare_id!` with constant
170// values is arguably the least-overhead approach to injecting static addresses
171// into the builtins list for both the feature ID and the source program ID.
172// These arbitrary IDs can then be used to configure feature-activation runtime
173// tests.
174#[cfg(any(test, feature = "dev-context-only-utils"))]
175pub mod test_only {
176    use crate::core_bpf_migration::{CoreBpfMigrationConfig, CoreBpfMigrationTargetType};
177    pub mod system_program {
178        pub mod feature {
179            solana_pubkey::declare_id!("AnjsdWg7LXFbjDdy78wncCJs9PyTdWpKkFmHAwQU1mQ6");
180        }
181        pub mod source_buffer {
182            solana_pubkey::declare_id!("EDEhzg1Jk79Wrk4mwpRa7txjgRxcE6igXwd6egFDVhuz");
183        }
184        pub mod upgrade_authority {
185            solana_pubkey::declare_id!("4d14UK2o1FKKoecEBWhVDZrBBbRuhug75G1j9XYCawC2");
186        }
187        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
188            source_buffer_address: source_buffer::id(),
189            upgrade_authority_address: Some(upgrade_authority::id()),
190            feature_id: feature::id(),
191            migration_target: super::CoreBpfMigrationTargetType::Builtin,
192            verified_build_hash: None,
193            datapoint_name: "migrate_builtin_to_core_bpf_system_program",
194        };
195    }
196
197    pub mod vote_program {
198        pub mod feature {
199            solana_pubkey::declare_id!("5wDLHMasPmtrcpfRZX67RVkBXBbSTQ9S4C8EJomD3yAk");
200        }
201        pub mod source_buffer {
202            solana_pubkey::declare_id!("6T9s4PTcHnpq2AVAqoCbJd4FuHsdD99MjSUEbS7qb1tT");
203        }
204        pub mod upgrade_authority {
205            solana_pubkey::declare_id!("2N4JfyYub6cWUP9R4JrsFHv6FYKT7JnoRX8GQUH9MdT3");
206        }
207        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
208            source_buffer_address: source_buffer::id(),
209            upgrade_authority_address: Some(upgrade_authority::id()),
210            feature_id: feature::id(),
211            migration_target: super::CoreBpfMigrationTargetType::Builtin,
212            verified_build_hash: None,
213            datapoint_name: "migrate_builtin_to_core_bpf_vote_program",
214        };
215    }
216
217    pub mod solana_bpf_loader_deprecated_program {
218        pub mod feature {
219            solana_pubkey::declare_id!("8gpakCv5Pk5PZGv9RUjzdkk2GVQPGx12cNRUDMQ3bP86");
220        }
221        pub mod source_buffer {
222            solana_pubkey::declare_id!("DveUYB5m9G3ce4zpV3fxg9pCNkvH1wDsyd8XberZ47JL");
223        }
224        pub mod upgrade_authority {
225            solana_pubkey::declare_id!("8Y5VTHdadnz4rZZWdUA4Qq2m2zWoCwwtb38spPZCXuGU");
226        }
227        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
228            source_buffer_address: source_buffer::id(),
229            upgrade_authority_address: Some(upgrade_authority::id()),
230            feature_id: feature::id(),
231            migration_target: super::CoreBpfMigrationTargetType::Builtin,
232            verified_build_hash: None,
233            datapoint_name: "migrate_builtin_to_core_bpf_bpf_loader_deprecated_program",
234        };
235    }
236
237    pub mod solana_bpf_loader_program {
238        pub mod feature {
239            solana_pubkey::declare_id!("8yEdUm4SaP1yNq2MczEVdrM48SucvZCTDSqjcAKfYfL6");
240        }
241        pub mod source_buffer {
242            solana_pubkey::declare_id!("2EWMYGJPuGLW4TexLLEMeXP2BkB1PXEKBFb698yw6LhT");
243        }
244        pub mod upgrade_authority {
245            solana_pubkey::declare_id!("3sQ9VZ1Lvuvs6NpFXFV3ByFAf52ajPPdXwuhYERJR3iJ");
246        }
247        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
248            source_buffer_address: source_buffer::id(),
249            upgrade_authority_address: Some(upgrade_authority::id()),
250            feature_id: feature::id(),
251            migration_target: super::CoreBpfMigrationTargetType::Builtin,
252            verified_build_hash: None,
253            datapoint_name: "migrate_builtin_to_core_bpf_bpf_loader_program",
254        };
255    }
256
257    pub mod solana_bpf_loader_upgradeable_program {
258        pub mod feature {
259            solana_pubkey::declare_id!("oPQbVjgoQ7SaQmzZiiHW4xqHbh4BJqqrFhxEJZiMiwY");
260        }
261        pub mod source_buffer {
262            solana_pubkey::declare_id!("6bTmA9iefD57GDoQ9wUjG8SeYkSpRw3EkKzxZCbhkavq");
263        }
264        pub mod upgrade_authority {
265            solana_pubkey::declare_id!("CuJvJY1K2wx82oLrQGSSWtw4AF7nVifEHupzSC2KEcq5");
266        }
267        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
268            source_buffer_address: source_buffer::id(),
269            upgrade_authority_address: Some(upgrade_authority::id()),
270            feature_id: feature::id(),
271            migration_target: super::CoreBpfMigrationTargetType::Builtin,
272            verified_build_hash: None,
273            datapoint_name: "migrate_builtin_to_core_bpf_bpf_loader_upgradeable_program",
274        };
275    }
276
277    pub mod compute_budget_program {
278        pub mod feature {
279            solana_pubkey::declare_id!("D39vUspVfhjPVD7EtMJZrA5j1TSMp4LXfb43nxumGdHT");
280        }
281        pub mod source_buffer {
282            solana_pubkey::declare_id!("KfX1oLpFC5CwmFeSgXrNcXaouKjFkPuSJ4UsKb3zKMX");
283        }
284        pub mod upgrade_authority {
285            solana_pubkey::declare_id!("HGTbQhaCXNTbpgpLb2KNjqWSwpJyb2dqDB66Lc3Ph4aN");
286        }
287        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
288            source_buffer_address: source_buffer::id(),
289            upgrade_authority_address: Some(upgrade_authority::id()),
290            feature_id: feature::id(),
291            migration_target: super::CoreBpfMigrationTargetType::Builtin,
292            verified_build_hash: None,
293            datapoint_name: "migrate_builtin_to_core_bpf_compute_budget_program",
294        };
295    }
296
297    pub mod zk_token_proof_program {
298        pub mod feature {
299            solana_pubkey::declare_id!("GfeFwUzKP9NmaP5u4VfnFgEvQoeQc2wPgnBFrUZhpib5");
300        }
301        pub mod source_buffer {
302            solana_pubkey::declare_id!("Ffe9gL8vXraBkiv3HqbLvBqY7i9V4qtZxjH83jYYDe1V");
303        }
304        pub mod upgrade_authority {
305            solana_pubkey::declare_id!("6zkXWHR8YeCvfMqHwyiz2n7g6hMUKCFhrVccZZTDk4ei");
306        }
307        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
308            source_buffer_address: source_buffer::id(),
309            upgrade_authority_address: Some(upgrade_authority::id()),
310            feature_id: feature::id(),
311            migration_target: super::CoreBpfMigrationTargetType::Builtin,
312            verified_build_hash: None,
313            datapoint_name: "migrate_builtin_to_core_bpf_zk_token_proof_program",
314        };
315    }
316
317    pub mod loader_v4 {
318        pub mod feature {
319            solana_pubkey::declare_id!("Cz5JthYp27KR3rwTCtVJhbRgwHCurbwcYX46D8setL22");
320        }
321        pub mod source_buffer {
322            solana_pubkey::declare_id!("EH45pKy1kzjifB93wEJi91js3S4HETdsteywR7ZCNPn5");
323        }
324        pub mod upgrade_authority {
325            solana_pubkey::declare_id!("AWbiYRbFts9GVX5uwUkwV46hTFP85PxCAM8e8ir8Hqtq");
326        }
327        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
328            source_buffer_address: source_buffer::id(),
329            upgrade_authority_address: Some(upgrade_authority::id()),
330            feature_id: feature::id(),
331            migration_target: super::CoreBpfMigrationTargetType::Builtin,
332            verified_build_hash: None,
333            datapoint_name: "migrate_builtin_to_core_bpf_loader_v4_program",
334        };
335    }
336
337    pub mod zk_elgamal_proof_program {
338        pub mod feature {
339            solana_pubkey::declare_id!("EYtuxScWqGWmcPEDmeUsEt3iPkvWE26EWLfSxUvWP2WN");
340        }
341        pub mod source_buffer {
342            solana_pubkey::declare_id!("AaVrLPurAUmjw6XRNGr6ezQfHaJWpBGHhcRSJmNjoVpQ");
343        }
344        pub mod upgrade_authority {
345            solana_pubkey::declare_id!("EyGkQYHgynUdvdNPNiWbJQk9roFCexgdJQMNcWbuvp78");
346        }
347        pub const CONFIG: super::CoreBpfMigrationConfig = super::CoreBpfMigrationConfig {
348            source_buffer_address: source_buffer::id(),
349            upgrade_authority_address: Some(upgrade_authority::id()),
350            feature_id: feature::id(),
351            migration_target: super::CoreBpfMigrationTargetType::Builtin,
352            verified_build_hash: None,
353            datapoint_name: "migrate_builtin_to_core_bpf_zk_elgamal_proof_program",
354        };
355    }
356}
357
358#[cfg(test)]
359mod tests {
360    // Since a macro is used to initialize the test IDs from the `test_only`
361    // module, best to ensure the lists have the expected values within a test
362    // context.
363    #[test]
364    fn test_testable_prototypes() {
365        assert_eq!(
366            &super::BUILTINS[0].core_bpf_migration_config,
367            &Some(super::test_only::system_program::CONFIG)
368        );
369        assert_eq!(
370            &super::BUILTINS[1].core_bpf_migration_config,
371            &Some(super::test_only::vote_program::CONFIG)
372        );
373        // Stake has a live migration config, so it has no test-only configs
374        // to test here.
375        assert_eq!(
376            &super::BUILTINS[3].core_bpf_migration_config,
377            &Some(super::test_only::solana_bpf_loader_deprecated_program::CONFIG)
378        );
379        assert_eq!(
380            &super::BUILTINS[4].core_bpf_migration_config,
381            &Some(super::test_only::solana_bpf_loader_program::CONFIG)
382        );
383        assert_eq!(
384            &super::BUILTINS[5].core_bpf_migration_config,
385            &Some(super::test_only::solana_bpf_loader_upgradeable_program::CONFIG)
386        );
387        assert_eq!(
388            &super::BUILTINS[6].core_bpf_migration_config,
389            &Some(super::test_only::compute_budget_program::CONFIG)
390        );
391        assert_eq!(
392            &super::BUILTINS[7].core_bpf_migration_config,
393            &Some(super::test_only::zk_token_proof_program::CONFIG)
394        );
395        assert_eq!(
396            &super::BUILTINS[8].core_bpf_migration_config,
397            &Some(super::test_only::loader_v4::CONFIG)
398        );
399        assert_eq!(
400            &super::BUILTINS[9].core_bpf_migration_config,
401            &Some(super::test_only::zk_elgamal_proof_program::CONFIG)
402        );
403    }
404}