1use solana_sdk::{
2 account::{Account, AccountSharedData},
3 bpf_loader,
4 bpf_loader_upgradeable::{self, get_program_data_address, UpgradeableLoaderState},
5 feature_set,
6 pubkey::Pubkey,
7 rent::Rent,
8};
9
10mod spl_memo_1_0 {
11 solana_sdk::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo");
12}
13mod spl_memo_3_0 {
14 solana_sdk::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
15}
16
17static SPL_PROGRAMS: &[(Pubkey, Pubkey, &[u8])] = &[
18 (
19 solana_inline_spl::token::ID,
20 solana_sdk_ids::bpf_loader::ID,
21 include_bytes!("programs/spl_token-3.5.0.so"),
22 ),
23 (
24 solana_inline_spl::token_2022::ID,
25 solana_sdk_ids::bpf_loader_upgradeable::ID,
26 include_bytes!("programs/spl_token_2022-5.0.2.so"),
27 ),
28 (
29 spl_memo_1_0::ID,
30 solana_sdk_ids::bpf_loader::ID,
31 include_bytes!("programs/spl_memo-1.0.0.so"),
32 ),
33 (
34 spl_memo_3_0::ID,
35 solana_sdk_ids::bpf_loader::ID,
36 include_bytes!("programs/spl_memo-3.0.0.so"),
37 ),
38 (
39 solana_inline_spl::associated_token_account::ID,
40 solana_sdk_ids::bpf_loader::ID,
41 include_bytes!("programs/spl_associated_token_account-1.1.1.so"),
42 ),
43];
44
45static CORE_BPF_PROGRAMS: &[(Pubkey, Pubkey, &[u8])] = &[
49 (
50 solana_sdk_ids::address_lookup_table::ID,
51 feature_set::migrate_address_lookup_table_program_to_core_bpf::ID,
52 include_bytes!("programs/core_bpf_address_lookup_table-3.0.0.so"),
53 ),
54 (
55 solana_sdk_ids::config::ID,
56 feature_set::migrate_config_program_to_core_bpf::ID,
57 include_bytes!("programs/core_bpf_config-3.0.0.so"),
58 ),
59 (
60 solana_sdk_ids::feature::ID,
61 feature_set::migrate_feature_gate_program_to_core_bpf::ID,
62 include_bytes!("programs/core_bpf_feature_gate-0.0.1.so"),
63 ),
64 ];
66
67fn bpf_loader_program_account(program_id: &Pubkey, elf: &[u8], rent: &Rent) -> (Pubkey, Account) {
71 (
72 *program_id,
73 Account {
74 lamports: rent.minimum_balance(elf.len()).max(1),
75 data: elf.to_vec(),
76 owner: bpf_loader::id(),
77 executable: true,
78 rent_epoch: 0,
79 },
80 )
81}
82
83pub(crate) fn bpf_loader_upgradeable_program_accounts(
90 program_id: &Pubkey,
91 elf: &[u8],
92 rent: &Rent,
93) -> [(Pubkey, Account); 2] {
94 let programdata_address = get_program_data_address(program_id);
95 let program_account = {
96 let space = UpgradeableLoaderState::size_of_program();
97 let lamports = rent.minimum_balance(space);
98 let data = bincode::serialize(&UpgradeableLoaderState::Program {
99 programdata_address,
100 })
101 .unwrap();
102 Account {
103 lamports,
104 data,
105 owner: bpf_loader_upgradeable::id(),
106 executable: true,
107 rent_epoch: 0,
108 }
109 };
110 let programdata_account = {
111 let space = UpgradeableLoaderState::size_of_programdata_metadata() + elf.len();
112 let lamports = rent.minimum_balance(space);
113 let mut data = bincode::serialize(&UpgradeableLoaderState::ProgramData {
114 slot: 0,
115 upgrade_authority_address: Some(Pubkey::default()),
116 })
117 .unwrap();
118 data.extend_from_slice(elf);
119 Account {
120 lamports,
121 data,
122 owner: bpf_loader_upgradeable::id(),
123 executable: false,
124 rent_epoch: 0,
125 }
126 };
127 [
128 (*program_id, program_account),
129 (programdata_address, programdata_account),
130 ]
131}
132
133pub fn spl_programs(rent: &Rent) -> Vec<(Pubkey, AccountSharedData)> {
134 SPL_PROGRAMS
135 .iter()
136 .flat_map(|(program_id, loader_id, elf)| {
137 let mut accounts = vec![];
138 if loader_id.eq(&solana_sdk_ids::bpf_loader_upgradeable::ID) {
139 for (key, account) in bpf_loader_upgradeable_program_accounts(program_id, elf, rent)
140 {
141 accounts.push((key, AccountSharedData::from(account)));
142 }
143 } else {
144 let (key, account) = bpf_loader_program_account(program_id, elf, rent);
145 accounts.push((key, AccountSharedData::from(account)));
146 }
147 accounts
148 })
149 .collect()
150}
151
152pub fn core_bpf_programs<F>(rent: &Rent, is_feature_active: F) -> Vec<(Pubkey, AccountSharedData)>
153where
154 F: Fn(&Pubkey) -> bool,
155{
156 CORE_BPF_PROGRAMS
157 .iter()
158 .flat_map(|(program_id, feature_id, elf)| {
159 let mut accounts = vec![];
160 if is_feature_active(feature_id) {
161 for (key, account) in bpf_loader_upgradeable_program_accounts(program_id, elf, rent)
162 {
163 accounts.push((key, AccountSharedData::from(account)));
164 }
165 }
166 accounts
167 })
168 .collect()
169}