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