2
2
//!
3
3
//! This is the loader of the program runtime v2.
4
4
5
- use crate :: pubkey:: Pubkey ;
5
+ use crate :: {
6
+ instruction:: { AccountMeta , Instruction } ,
7
+ loader_v4_instruction:: LoaderV4Instruction ,
8
+ pubkey:: Pubkey ,
9
+ system_instruction,
10
+ } ;
6
11
7
12
crate :: declare_id!( "LoaderV411111111111111111111111111111111111" ) ;
8
13
@@ -41,9 +46,147 @@ impl LoaderV4State {
41
46
}
42
47
}
43
48
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
+
44
187
#[ cfg( test) ]
45
188
mod tests {
46
- use { super :: * , memoffset:: offset_of} ;
189
+ use { super :: * , crate :: system_program , memoffset:: offset_of} ;
47
190
48
191
#[ test]
49
192
fn test_layout ( ) {
@@ -52,4 +195,161 @@ mod tests {
52
195
assert_eq ! ( offset_of!( LoaderV4State , status) , 0x28 ) ;
53
196
assert_eq ! ( LoaderV4State :: program_data_offset( ) , 0x30 ) ;
54
197
}
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
+ }
55
355
}
0 commit comments