1use serde::Serialize;
2use gemachain_sdk::{
3 bpf_loader_upgradeable::{self, UpgradeableLoaderState},
4 client::Client,
5 instruction::{AccountMeta, Instruction},
6 loader_instruction,
7 message::Message,
8 pubkey::Pubkey,
9 signature::{Keypair, Signer},
10 system_instruction,
11};
12
13pub fn load_program<T: Client>(
14 bank_client: &T,
15 from_keypair: &Keypair,
16 loader_pubkey: &Pubkey,
17 program: Vec<u8>,
18) -> Pubkey {
19 let program_keypair = Keypair::new();
20 let program_pubkey = program_keypair.pubkey();
21
22 let instruction = system_instruction::create_account(
23 &from_keypair.pubkey(),
24 &program_pubkey,
25 1.max(
26 bank_client
27 .get_minimum_balance_for_rent_exemption(program.len())
28 .unwrap(),
29 ),
30 program.len() as u64,
31 loader_pubkey,
32 );
33 bank_client
34 .send_and_confirm_message(
35 &[from_keypair, &program_keypair],
36 Message::new(&[instruction], Some(&from_keypair.pubkey())),
37 )
38 .unwrap();
39
40 let chunk_size = 256; let mut offset = 0;
42 for chunk in program.chunks(chunk_size) {
43 let instruction =
44 loader_instruction::write(&program_pubkey, loader_pubkey, offset, chunk.to_vec());
45 let message = Message::new(&[instruction], Some(&from_keypair.pubkey()));
46 bank_client
47 .send_and_confirm_message(&[from_keypair, &program_keypair], message)
48 .unwrap();
49 offset += chunk_size as u32;
50 }
51
52 let instruction = loader_instruction::finalize(&program_pubkey, loader_pubkey);
53 let message = Message::new(&[instruction], Some(&from_keypair.pubkey()));
54 bank_client
55 .send_and_confirm_message(&[from_keypair, &program_keypair], message)
56 .unwrap();
57
58 program_pubkey
59}
60
61pub fn load_buffer_account<T: Client>(
62 bank_client: &T,
63 from_keypair: &Keypair,
64 buffer_keypair: &Keypair,
65 buffer_authority_keypair: &Keypair,
66 program: &[u8],
67) {
68 let buffer_pubkey = buffer_keypair.pubkey();
69 let buffer_authority_pubkey = buffer_authority_keypair.pubkey();
70
71 bank_client
72 .send_and_confirm_message(
73 &[from_keypair, buffer_keypair],
74 Message::new(
75 &bpf_loader_upgradeable::create_buffer(
76 &from_keypair.pubkey(),
77 &buffer_pubkey,
78 &buffer_authority_pubkey,
79 1.max(
80 bank_client
81 .get_minimum_balance_for_rent_exemption(program.len())
82 .unwrap(),
83 ),
84 program.len(),
85 )
86 .unwrap(),
87 Some(&from_keypair.pubkey()),
88 ),
89 )
90 .unwrap();
91
92 let chunk_size = 256; let mut offset = 0;
94 for chunk in program.chunks(chunk_size) {
95 let message = Message::new(
96 &[bpf_loader_upgradeable::write(
97 &buffer_pubkey,
98 &buffer_authority_pubkey,
99 offset,
100 chunk.to_vec(),
101 )],
102 Some(&from_keypair.pubkey()),
103 );
104 bank_client
105 .send_and_confirm_message(&[from_keypair, buffer_authority_keypair], message)
106 .unwrap();
107 offset += chunk_size as u32;
108 }
109}
110
111pub fn load_upgradeable_program<T: Client>(
112 bank_client: &T,
113 from_keypair: &Keypair,
114 buffer_keypair: &Keypair,
115 executable_keypair: &Keypair,
116 authority_keypair: &Keypair,
117 program: Vec<u8>,
118) {
119 let program_pubkey = executable_keypair.pubkey();
120 let authority_pubkey = authority_keypair.pubkey();
121
122 load_buffer_account(
123 bank_client,
124 from_keypair,
125 buffer_keypair,
126 authority_keypair,
127 &program,
128 );
129
130 let message = Message::new(
131 &bpf_loader_upgradeable::deploy_with_max_program_len(
132 &from_keypair.pubkey(),
133 &program_pubkey,
134 &buffer_keypair.pubkey(),
135 &authority_pubkey,
136 1.max(
137 bank_client
138 .get_minimum_balance_for_rent_exemption(
139 UpgradeableLoaderState::program_len().unwrap(),
140 )
141 .unwrap(),
142 ),
143 program.len() * 2,
144 )
145 .unwrap(),
146 Some(&from_keypair.pubkey()),
147 );
148 bank_client
149 .send_and_confirm_message(
150 &[from_keypair, executable_keypair, authority_keypair],
151 message,
152 )
153 .unwrap();
154}
155
156pub fn upgrade_program<T: Client>(
157 bank_client: &T,
158 from_keypair: &Keypair,
159 program_pubkey: &Pubkey,
160 buffer_pubkey: &Pubkey,
161 authority_keypair: &Keypair,
162 spill_pubkey: &Pubkey,
163) {
164 let message = Message::new(
165 &[bpf_loader_upgradeable::upgrade(
166 program_pubkey,
167 buffer_pubkey,
168 &authority_keypair.pubkey(),
169 spill_pubkey,
170 )],
171 Some(&from_keypair.pubkey()),
172 );
173 bank_client
174 .send_and_confirm_message(&[from_keypair, authority_keypair], message)
175 .unwrap();
176}
177
178pub fn set_upgrade_authority<T: Client>(
179 bank_client: &T,
180 from_keypair: &Keypair,
181 program_pubkey: &Pubkey,
182 current_authority_keypair: &Keypair,
183 new_authority_pubkey: Option<&Pubkey>,
184) {
185 let message = Message::new(
186 &[bpf_loader_upgradeable::set_upgrade_authority(
187 program_pubkey,
188 ¤t_authority_keypair.pubkey(),
189 new_authority_pubkey,
190 )],
191 Some(&from_keypair.pubkey()),
192 );
193 bank_client
194 .send_and_confirm_message(&[from_keypair, current_authority_keypair], message)
195 .unwrap();
196}
197
198pub fn create_invoke_instruction<T: Serialize>(
201 from_pubkey: Pubkey,
202 program_id: Pubkey,
203 data: &T,
204) -> Instruction {
205 let account_metas = vec![AccountMeta::new(from_pubkey, true)];
206 Instruction::new_with_bincode(program_id, data, account_metas)
207}