1use {
2 solana_account::{Account, AccountSharedData},
3 solana_loader_v3_interface::{get_program_data_address, state::UpgradeableLoaderState},
4 solana_pubkey::Pubkey,
5 solana_rent::Rent,
6 solana_sdk_ids::{bpf_loader, bpf_loader_upgradeable},
7};
8
9mod spl_memo_1_0 {
10 solana_pubkey::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo");
11}
12mod spl_memo_3_0 {
13 solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
14}
15
16static SPL_PROGRAMS: &[(Pubkey, Pubkey, &[u8])] = &[
17 (
18 spl_generic_token::token::ID,
19 solana_sdk_ids::bpf_loader::ID,
20 include_bytes!("programs/spl_token-3.5.0.so"),
21 ),
22 (
23 spl_generic_token::token_2022::ID,
24 solana_sdk_ids::bpf_loader_upgradeable::ID,
25 include_bytes!("programs/spl_token_2022-8.0.0.so"),
26 ),
27 (
28 spl_memo_1_0::ID,
29 solana_sdk_ids::bpf_loader::ID,
30 include_bytes!("programs/spl_memo-1.0.0.so"),
31 ),
32 (
33 spl_memo_3_0::ID,
34 solana_sdk_ids::bpf_loader::ID,
35 include_bytes!("programs/spl_memo-3.0.0.so"),
36 ),
37 (
38 spl_generic_token::associated_token_account::ID,
39 solana_sdk_ids::bpf_loader::ID,
40 include_bytes!("programs/spl_associated_token_account-1.1.1.so"),
41 ),
42];
43
44static CORE_BPF_PROGRAMS: &[(Pubkey, Option<Pubkey>, &[u8])] = &[
49 (
50 solana_sdk_ids::address_lookup_table::ID,
51 None,
52 include_bytes!("programs/core_bpf_address_lookup_table-3.0.0.so"),
53 ),
54 (
55 solana_sdk_ids::config::ID,
56 None,
57 include_bytes!("programs/core_bpf_config-3.0.0.so"),
58 ),
59 (
60 solana_sdk_ids::feature::ID,
61 None,
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 feature_id.is_none() || feature_id.is_some_and(|f| is_feature_active(&f)) {
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}