Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit a3399d0

Browse files
authored
Add loader-v4 instruction constructors (#33151)
* Add loader-v4 instruction constructors * address review comments * clippy fixes
1 parent f8d304c commit a3399d0

File tree

1 file changed

+302
-2
lines changed

1 file changed

+302
-2
lines changed

sdk/program/src/loader_v4.rs

Lines changed: 302 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
//!
33
//! This is the loader of the program runtime v2.
44
5-
use crate::pubkey::Pubkey;
5+
use crate::{
6+
instruction::{AccountMeta, Instruction},
7+
loader_v4_instruction::LoaderV4Instruction,
8+
pubkey::Pubkey,
9+
system_instruction,
10+
};
611

712
crate::declare_id!("LoaderV411111111111111111111111111111111111");
813

@@ -41,9 +46,147 @@ impl LoaderV4State {
4146
}
4247
}
4348

49+
pub fn is_write_instruction(instruction_data: &[u8]) -> bool {
50+
!instruction_data.is_empty() && 0 == instruction_data[0]
51+
}
52+
53+
pub fn is_truncate_instruction(instruction_data: &[u8]) -> bool {
54+
!instruction_data.is_empty() && 1 == instruction_data[0]
55+
}
56+
57+
pub fn is_deploy_instruction(instruction_data: &[u8]) -> bool {
58+
!instruction_data.is_empty() && 2 == instruction_data[0]
59+
}
60+
61+
pub fn is_retract_instruction(instruction_data: &[u8]) -> bool {
62+
!instruction_data.is_empty() && 3 == instruction_data[0]
63+
}
64+
65+
pub fn is_transfer_authority_instruction(instruction_data: &[u8]) -> bool {
66+
!instruction_data.is_empty() && 4 == instruction_data[0]
67+
}
68+
69+
/// Returns the instructions required to initialize a program/buffer account.
70+
pub fn create_buffer(
71+
payer_address: &Pubkey,
72+
buffer_address: &Pubkey,
73+
lamports: u64,
74+
authority: &Pubkey,
75+
new_size: u32,
76+
recipient_address: &Pubkey,
77+
) -> Vec<Instruction> {
78+
vec![
79+
system_instruction::create_account(payer_address, buffer_address, lamports, 0, &id()),
80+
Instruction::new_with_bincode(
81+
id(),
82+
&LoaderV4Instruction::Truncate { new_size },
83+
vec![
84+
AccountMeta::new(*buffer_address, true),
85+
AccountMeta::new_readonly(*authority, true),
86+
AccountMeta::new(*recipient_address, false),
87+
],
88+
),
89+
]
90+
}
91+
92+
/// Returns the instructions required to set the length of the program account.
93+
pub fn truncate(
94+
program_address: &Pubkey,
95+
authority: &Pubkey,
96+
new_size: u32,
97+
recipient_address: &Pubkey,
98+
) -> Instruction {
99+
Instruction::new_with_bincode(
100+
id(),
101+
&LoaderV4Instruction::Truncate { new_size },
102+
vec![
103+
AccountMeta::new(*program_address, false),
104+
AccountMeta::new_readonly(*authority, true),
105+
AccountMeta::new(*recipient_address, false),
106+
],
107+
)
108+
}
109+
110+
/// Returns the instructions required to write a chunk of program data to a
111+
/// buffer account.
112+
pub fn write(
113+
program_address: &Pubkey,
114+
authority: &Pubkey,
115+
offset: u32,
116+
bytes: Vec<u8>,
117+
) -> Instruction {
118+
Instruction::new_with_bincode(
119+
id(),
120+
&LoaderV4Instruction::Write { offset, bytes },
121+
vec![
122+
AccountMeta::new(*program_address, false),
123+
AccountMeta::new_readonly(*authority, true),
124+
],
125+
)
126+
}
127+
128+
/// Returns the instructions required to deploy a program.
129+
pub fn deploy(program_address: &Pubkey, authority: &Pubkey) -> Instruction {
130+
Instruction::new_with_bincode(
131+
id(),
132+
&LoaderV4Instruction::Deploy,
133+
vec![
134+
AccountMeta::new(*program_address, false),
135+
AccountMeta::new_readonly(*authority, true),
136+
],
137+
)
138+
}
139+
140+
/// Returns the instructions required to deploy a program using a buffer.
141+
pub fn deploy_from_source(
142+
program_address: &Pubkey,
143+
authority: &Pubkey,
144+
source_address: &Pubkey,
145+
) -> Instruction {
146+
Instruction::new_with_bincode(
147+
id(),
148+
&LoaderV4Instruction::Deploy,
149+
vec![
150+
AccountMeta::new(*program_address, false),
151+
AccountMeta::new_readonly(*authority, true),
152+
AccountMeta::new(*source_address, false),
153+
],
154+
)
155+
}
156+
157+
/// Returns the instructions required to retract a program.
158+
pub fn retract(program_address: &Pubkey, authority: &Pubkey) -> Instruction {
159+
Instruction::new_with_bincode(
160+
id(),
161+
&LoaderV4Instruction::Retract,
162+
vec![
163+
AccountMeta::new(*program_address, false),
164+
AccountMeta::new_readonly(*authority, true),
165+
],
166+
)
167+
}
168+
169+
/// Returns the instructions required to transfer authority over a program.
170+
pub fn transfer_authority(
171+
program_address: &Pubkey,
172+
authority: &Pubkey,
173+
new_authority: Option<&Pubkey>,
174+
) -> Instruction {
175+
let mut accounts = vec![
176+
AccountMeta::new(*program_address, false),
177+
AccountMeta::new_readonly(*authority, true),
178+
];
179+
180+
if let Some(new_auth) = new_authority {
181+
accounts.push(AccountMeta::new_readonly(*new_auth, true));
182+
}
183+
184+
Instruction::new_with_bincode(id(), &LoaderV4Instruction::TransferAuthority, accounts)
185+
}
186+
44187
#[cfg(test)]
45188
mod tests {
46-
use {super::*, memoffset::offset_of};
189+
use {super::*, crate::system_program, memoffset::offset_of};
47190

48191
#[test]
49192
fn test_layout() {
@@ -52,4 +195,161 @@ mod tests {
52195
assert_eq!(offset_of!(LoaderV4State, status), 0x28);
53196
assert_eq!(LoaderV4State::program_data_offset(), 0x30);
54197
}
198+
199+
#[test]
200+
fn test_create_buffer_instruction() {
201+
let payer = Pubkey::new_unique();
202+
let program = Pubkey::new_unique();
203+
let authority = Pubkey::new_unique();
204+
let recipient = Pubkey::new_unique();
205+
let instructions = create_buffer(&payer, &program, 123, &authority, 10, &recipient);
206+
assert_eq!(instructions.len(), 2);
207+
let instruction0 = &instructions[0];
208+
assert_eq!(instruction0.program_id, system_program::id());
209+
assert_eq!(instruction0.accounts.len(), 2);
210+
assert_eq!(instruction0.accounts[0].pubkey, payer);
211+
assert!(instruction0.accounts[0].is_writable);
212+
assert!(instruction0.accounts[0].is_signer);
213+
assert_eq!(instruction0.accounts[1].pubkey, program);
214+
assert!(instruction0.accounts[1].is_writable);
215+
assert!(instruction0.accounts[1].is_signer);
216+
217+
let instruction1 = &instructions[1];
218+
assert!(is_truncate_instruction(&instruction1.data));
219+
assert_eq!(instruction1.program_id, id());
220+
assert_eq!(instruction1.accounts.len(), 3);
221+
assert_eq!(instruction1.accounts[0].pubkey, program);
222+
assert!(instruction1.accounts[0].is_writable);
223+
assert!(instruction1.accounts[0].is_signer);
224+
assert_eq!(instruction1.accounts[1].pubkey, authority);
225+
assert!(!instruction1.accounts[1].is_writable);
226+
assert!(instruction1.accounts[1].is_signer);
227+
assert_eq!(instruction1.accounts[2].pubkey, recipient);
228+
assert!(instruction1.accounts[2].is_writable);
229+
assert!(!instruction1.accounts[2].is_signer);
230+
}
231+
232+
#[test]
233+
fn test_write_instruction() {
234+
let program = Pubkey::new_unique();
235+
let authority = Pubkey::new_unique();
236+
let instruction = write(&program, &authority, 123, vec![1, 2, 3, 4]);
237+
assert!(is_write_instruction(&instruction.data));
238+
assert_eq!(instruction.program_id, id());
239+
assert_eq!(instruction.accounts.len(), 2);
240+
assert_eq!(instruction.accounts[0].pubkey, program);
241+
assert!(instruction.accounts[0].is_writable);
242+
assert!(!instruction.accounts[0].is_signer);
243+
assert_eq!(instruction.accounts[1].pubkey, authority);
244+
assert!(!instruction.accounts[1].is_writable);
245+
assert!(instruction.accounts[1].is_signer);
246+
}
247+
248+
#[test]
249+
fn test_truncate_instruction() {
250+
let program = Pubkey::new_unique();
251+
let authority = Pubkey::new_unique();
252+
let recipient = Pubkey::new_unique();
253+
let instruction = truncate(&program, &authority, 10, &recipient);
254+
assert!(is_truncate_instruction(&instruction.data));
255+
assert_eq!(instruction.program_id, id());
256+
assert_eq!(instruction.accounts.len(), 3);
257+
assert_eq!(instruction.accounts[0].pubkey, program);
258+
assert!(instruction.accounts[0].is_writable);
259+
assert!(!instruction.accounts[0].is_signer);
260+
assert_eq!(instruction.accounts[1].pubkey, authority);
261+
assert!(!instruction.accounts[1].is_writable);
262+
assert!(instruction.accounts[1].is_signer);
263+
assert_eq!(instruction.accounts[2].pubkey, recipient);
264+
assert!(instruction.accounts[2].is_writable);
265+
assert!(!instruction.accounts[2].is_signer);
266+
}
267+
268+
#[test]
269+
fn test_deploy_instruction() {
270+
let program = Pubkey::new_unique();
271+
let authority = Pubkey::new_unique();
272+
let instruction = deploy(&program, &authority);
273+
assert!(is_deploy_instruction(&instruction.data));
274+
assert_eq!(instruction.program_id, id());
275+
assert_eq!(instruction.accounts.len(), 2);
276+
assert_eq!(instruction.accounts[0].pubkey, program);
277+
assert!(instruction.accounts[0].is_writable);
278+
assert!(!instruction.accounts[0].is_signer);
279+
assert_eq!(instruction.accounts[1].pubkey, authority);
280+
assert!(!instruction.accounts[1].is_writable);
281+
assert!(instruction.accounts[1].is_signer);
282+
}
283+
284+
#[test]
285+
fn test_deploy_from_source_instruction() {
286+
let program = Pubkey::new_unique();
287+
let authority = Pubkey::new_unique();
288+
let source = Pubkey::new_unique();
289+
let instruction = deploy_from_source(&program, &authority, &source);
290+
assert!(is_deploy_instruction(&instruction.data));
291+
assert_eq!(instruction.program_id, id());
292+
assert_eq!(instruction.accounts.len(), 3);
293+
assert_eq!(instruction.accounts[0].pubkey, program);
294+
assert!(instruction.accounts[0].is_writable);
295+
assert!(!instruction.accounts[0].is_signer);
296+
assert_eq!(instruction.accounts[1].pubkey, authority);
297+
assert!(!instruction.accounts[1].is_writable);
298+
assert!(instruction.accounts[1].is_signer);
299+
assert_eq!(instruction.accounts[2].pubkey, source);
300+
assert!(instruction.accounts[2].is_writable);
301+
assert!(!instruction.accounts[2].is_signer);
302+
}
303+
304+
#[test]
305+
fn test_retract_instruction() {
306+
let program = Pubkey::new_unique();
307+
let authority = Pubkey::new_unique();
308+
let instruction = retract(&program, &authority);
309+
assert!(is_retract_instruction(&instruction.data));
310+
assert_eq!(instruction.program_id, id());
311+
assert_eq!(instruction.accounts.len(), 2);
312+
assert_eq!(instruction.accounts[0].pubkey, program);
313+
assert!(instruction.accounts[0].is_writable);
314+
assert!(!instruction.accounts[0].is_signer);
315+
assert_eq!(instruction.accounts[1].pubkey, authority);
316+
assert!(!instruction.accounts[1].is_writable);
317+
assert!(instruction.accounts[1].is_signer);
318+
}
319+
320+
#[test]
321+
fn test_transfer_authority_instruction() {
322+
let program = Pubkey::new_unique();
323+
let authority = Pubkey::new_unique();
324+
let new_authority = Pubkey::new_unique();
325+
let instruction = transfer_authority(&program, &authority, Some(&new_authority));
326+
assert!(is_transfer_authority_instruction(&instruction.data));
327+
assert_eq!(instruction.program_id, id());
328+
assert_eq!(instruction.accounts.len(), 3);
329+
assert_eq!(instruction.accounts[0].pubkey, program);
330+
assert!(instruction.accounts[0].is_writable);
331+
assert!(!instruction.accounts[0].is_signer);
332+
assert_eq!(instruction.accounts[1].pubkey, authority);
333+
assert!(!instruction.accounts[1].is_writable);
334+
assert!(instruction.accounts[1].is_signer);
335+
assert_eq!(instruction.accounts[2].pubkey, new_authority);
336+
assert!(!instruction.accounts[2].is_writable);
337+
assert!(instruction.accounts[2].is_signer);
338+
}
339+
340+
#[test]
341+
fn test_transfer_authority_finalize_instruction() {
342+
let program = Pubkey::new_unique();
343+
let authority = Pubkey::new_unique();
344+
let instruction = transfer_authority(&program, &authority, None);
345+
assert!(is_transfer_authority_instruction(&instruction.data));
346+
assert_eq!(instruction.program_id, id());
347+
assert_eq!(instruction.accounts.len(), 2);
348+
assert_eq!(instruction.accounts[0].pubkey, program);
349+
assert!(instruction.accounts[0].is_writable);
350+
assert!(!instruction.accounts[0].is_signer);
351+
assert_eq!(instruction.accounts[1].pubkey, authority);
352+
assert!(!instruction.accounts[1].is_writable);
353+
assert!(instruction.accounts[1].is_signer);
354+
}
55355
}

0 commit comments

Comments
 (0)