1use {
4 crate::ConfigKeys, bincode::deserialize, solana_bincode::limited_deserialize,
5 solana_instruction::error::InstructionError, solana_log_collector::ic_msg,
6 solana_program_runtime::declare_process_instruction, solana_pubkey::Pubkey,
7 solana_transaction_context::IndexOfAccount, std::collections::BTreeSet,
8};
9
10pub const DEFAULT_COMPUTE_UNITS: u64 = 450;
11
12declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context| {
13 let transaction_context = &invoke_context.transaction_context;
14 let instruction_context = transaction_context.get_current_instruction_context()?;
15 let data = instruction_context.get_instruction_data();
16
17 let key_list: ConfigKeys = limited_deserialize(data, solana_packet::PACKET_DATA_SIZE as u64)?;
18 let config_account_key = transaction_context.get_key_of_account_at_index(
19 instruction_context.get_index_of_instruction_account_in_transaction(0)?,
20 )?;
21 let config_account =
22 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
23 let is_config_account_signer = config_account.is_signer();
24 let current_data: ConfigKeys = {
25 if config_account.get_owner() != &crate::id() {
26 return Err(InstructionError::InvalidAccountOwner);
27 }
28
29 deserialize(config_account.get_data()).map_err(|err| {
30 ic_msg!(
31 invoke_context,
32 "Unable to deserialize config account: {}",
33 err
34 );
35 InstructionError::InvalidAccountData
36 })?
37 };
38 drop(config_account);
39
40 let current_signer_keys: Vec<Pubkey> = current_data
41 .keys
42 .iter()
43 .filter(|(_, is_signer)| *is_signer)
44 .map(|(pubkey, _)| *pubkey)
45 .collect();
46 if current_signer_keys.is_empty() {
47 if !is_config_account_signer {
50 return Err(InstructionError::MissingRequiredSignature);
51 }
52 }
53
54 let mut counter = 0;
55 for (signer, _) in key_list.keys.iter().filter(|(_, is_signer)| *is_signer) {
56 counter += 1;
57 if signer != config_account_key {
58 let signer_account = instruction_context
59 .try_borrow_instruction_account(transaction_context, counter as IndexOfAccount)
60 .map_err(|_| {
61 ic_msg!(
62 invoke_context,
63 "account {:?} is not in account list",
64 signer,
65 );
66 InstructionError::MissingRequiredSignature
67 })?;
68 if !signer_account.is_signer() {
69 ic_msg!(
70 invoke_context,
71 "account {:?} signer_key().is_none()",
72 signer
73 );
74 return Err(InstructionError::MissingRequiredSignature);
75 }
76 if signer_account.get_key() != signer {
77 ic_msg!(
78 invoke_context,
79 "account[{:?}].signer_key() does not match Config data)",
80 counter + 1
81 );
82 return Err(InstructionError::MissingRequiredSignature);
83 }
84 if !current_data.keys.is_empty()
86 && !current_signer_keys.iter().any(|pubkey| pubkey == signer)
87 {
88 ic_msg!(
89 invoke_context,
90 "account {:?} is not in stored signer list",
91 signer
92 );
93 return Err(InstructionError::MissingRequiredSignature);
94 }
95 } else if !is_config_account_signer {
96 ic_msg!(invoke_context, "account[0].signer_key().is_none()");
97 return Err(InstructionError::MissingRequiredSignature);
98 }
99 }
100
101 let total_new_keys = key_list.keys.len();
103 let unique_new_keys = key_list.keys.into_iter().collect::<BTreeSet<_>>();
104 if unique_new_keys.len() != total_new_keys {
105 ic_msg!(invoke_context, "new config contains duplicate keys");
106 return Err(InstructionError::InvalidArgument);
107 }
108
109 if current_signer_keys.len() > counter {
111 ic_msg!(
112 invoke_context,
113 "too few signers: {:?}; expected: {:?}",
114 counter,
115 current_signer_keys.len()
116 );
117 return Err(InstructionError::MissingRequiredSignature);
118 }
119
120 let mut config_account =
121 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
122 if config_account.get_data().len() < data.len() {
123 ic_msg!(invoke_context, "instruction data too large");
124 return Err(InstructionError::InvalidInstructionData);
125 }
126 config_account.get_data_mut()?[..data.len()].copy_from_slice(data);
127 Ok(())
128});
129
130#[cfg(test)]
131mod tests {
132 use {
133 super::*,
134 crate::{config_instruction, get_config_data, id, ConfigKeys, ConfigState},
135 bincode::serialized_size,
136 serde_derive::{Deserialize, Serialize},
137 solana_account::{AccountSharedData, ReadableAccount},
138 solana_instruction::AccountMeta,
139 solana_keypair::Keypair,
140 solana_program_runtime::invoke_context::mock_process_instruction,
141 solana_pubkey::Pubkey,
142 solana_signer::Signer,
143 solana_system_interface::instruction::SystemInstruction,
144 };
145
146 fn process_instruction(
147 instruction_data: &[u8],
148 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
149 instruction_accounts: Vec<AccountMeta>,
150 expected_result: Result<(), InstructionError>,
151 ) -> Vec<AccountSharedData> {
152 mock_process_instruction(
153 &id(),
154 Vec::new(),
155 instruction_data,
156 transaction_accounts,
157 instruction_accounts,
158 expected_result,
159 Entrypoint::vm,
160 |_invoke_context| {},
161 |_invoke_context| {},
162 )
163 }
164
165 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
166 struct MyConfig {
167 pub item: u64,
168 }
169 impl Default for MyConfig {
170 fn default() -> Self {
171 Self { item: 123_456_789 }
172 }
173 }
174 impl MyConfig {
175 pub fn new(item: u64) -> Self {
176 Self { item }
177 }
178 pub fn deserialize(input: &[u8]) -> Option<Self> {
179 deserialize(input).ok()
180 }
181 }
182
183 impl ConfigState for MyConfig {
184 fn max_space() -> u64 {
185 serialized_size(&Self::default()).unwrap()
186 }
187 }
188
189 fn create_config_account(keys: Vec<(Pubkey, bool)>) -> (Keypair, AccountSharedData) {
190 let from_pubkey = Pubkey::new_unique();
191 let config_keypair = Keypair::new();
192 let config_pubkey = config_keypair.pubkey();
193 let instructions =
194 config_instruction::create_account::<MyConfig>(&from_pubkey, &config_pubkey, 1, keys);
195 let system_instruction = limited_deserialize(
196 &instructions[0].data,
197 solana_packet::PACKET_DATA_SIZE as u64,
198 )
199 .unwrap();
200 let SystemInstruction::CreateAccount {
201 lamports: _,
202 space,
203 owner: _,
204 } = system_instruction
205 else {
206 panic!("Not a CreateAccount system instruction")
207 };
208 let config_account = AccountSharedData::new(0, space as usize, &id());
209 let accounts = process_instruction(
210 &instructions[1].data,
211 vec![(config_pubkey, config_account)],
212 vec![AccountMeta {
213 pubkey: config_pubkey,
214 is_signer: true,
215 is_writable: true,
216 }],
217 Ok(()),
218 );
219 (config_keypair, accounts[0].clone())
220 }
221
222 #[test]
223 fn test_process_create_ok() {
224 solana_logger::setup();
225 let (_, config_account) = create_config_account(vec![]);
226 assert_eq!(
227 Some(MyConfig::default()),
228 deserialize(get_config_data(config_account.data()).unwrap()).ok()
229 );
230 }
231
232 #[test]
233 fn test_process_store_ok() {
234 solana_logger::setup();
235 let keys = vec![];
236 let (config_keypair, config_account) = create_config_account(keys.clone());
237 let config_pubkey = config_keypair.pubkey();
238 let my_config = MyConfig::new(42);
239
240 let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
241 let accounts = process_instruction(
242 &instruction.data,
243 vec![(config_pubkey, config_account)],
244 vec![AccountMeta {
245 pubkey: config_pubkey,
246 is_signer: true,
247 is_writable: true,
248 }],
249 Ok(()),
250 );
251 assert_eq!(
252 Some(my_config),
253 deserialize(get_config_data(accounts[0].data()).unwrap()).ok()
254 );
255 }
256
257 #[test]
258 fn test_process_store_fail_instruction_data_too_large() {
259 solana_logger::setup();
260 let keys = vec![];
261 let (config_keypair, config_account) = create_config_account(keys.clone());
262 let config_pubkey = config_keypair.pubkey();
263 let my_config = MyConfig::new(42);
264
265 let mut instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
266 instruction.data = vec![0; 123]; process_instruction(
268 &instruction.data,
269 vec![(config_pubkey, config_account)],
270 vec![AccountMeta {
271 pubkey: config_pubkey,
272 is_signer: true,
273 is_writable: true,
274 }],
275 Err(InstructionError::InvalidInstructionData),
276 );
277 }
278
279 #[test]
280 fn test_process_store_fail_account0_not_signer() {
281 solana_logger::setup();
282 let keys = vec![];
283 let (config_keypair, config_account) = create_config_account(keys);
284 let config_pubkey = config_keypair.pubkey();
285 let my_config = MyConfig::new(42);
286
287 let mut instruction = config_instruction::store(&config_pubkey, true, vec![], &my_config);
288 instruction.accounts[0].is_signer = false; process_instruction(
290 &instruction.data,
291 vec![(config_pubkey, config_account)],
292 vec![AccountMeta {
293 pubkey: config_pubkey,
294 is_signer: false,
295 is_writable: true,
296 }],
297 Err(InstructionError::MissingRequiredSignature),
298 );
299 }
300
301 #[test]
302 fn test_process_store_with_additional_signers() {
303 solana_logger::setup();
304 let pubkey = Pubkey::new_unique();
305 let signer0_pubkey = Pubkey::new_unique();
306 let signer1_pubkey = Pubkey::new_unique();
307 let keys = vec![
308 (pubkey, false),
309 (signer0_pubkey, true),
310 (signer1_pubkey, true),
311 ];
312 let (config_keypair, config_account) = create_config_account(keys.clone());
313 let config_pubkey = config_keypair.pubkey();
314 let my_config = MyConfig::new(42);
315 let signer0_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
316 let signer1_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
317
318 let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
319 let accounts = process_instruction(
320 &instruction.data,
321 vec![
322 (config_pubkey, config_account),
323 (signer0_pubkey, signer0_account),
324 (signer1_pubkey, signer1_account),
325 ],
326 vec![
327 AccountMeta {
328 pubkey: config_pubkey,
329 is_signer: true,
330 is_writable: true,
331 },
332 AccountMeta {
333 pubkey: signer0_pubkey,
334 is_signer: true,
335 is_writable: false,
336 },
337 AccountMeta {
338 pubkey: signer1_pubkey,
339 is_signer: true,
340 is_writable: false,
341 },
342 ],
343 Ok(()),
344 );
345 let meta_data: ConfigKeys = deserialize(accounts[0].data()).unwrap();
346 assert_eq!(meta_data.keys, keys);
347 assert_eq!(
348 Some(my_config),
349 deserialize(get_config_data(accounts[0].data()).unwrap()).ok()
350 );
351 }
352
353 #[test]
354 fn test_process_store_without_config_signer() {
355 solana_logger::setup();
356 let pubkey = Pubkey::new_unique();
357 let signer0_pubkey = Pubkey::new_unique();
358 let keys = vec![(pubkey, false), (signer0_pubkey, true)];
359 let (config_keypair, _) = create_config_account(keys.clone());
360 let config_pubkey = config_keypair.pubkey();
361 let my_config = MyConfig::new(42);
362 let signer0_account = AccountSharedData::new(0, 0, &id());
363
364 let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
365 process_instruction(
366 &instruction.data,
367 vec![(signer0_pubkey, signer0_account)],
368 vec![AccountMeta {
369 pubkey: signer0_pubkey,
370 is_signer: true,
371 is_writable: false,
372 }],
373 Err(InstructionError::InvalidAccountData),
374 );
375 }
376
377 #[test]
378 fn test_process_store_with_bad_additional_signer() {
379 solana_logger::setup();
380 let signer0_pubkey = Pubkey::new_unique();
381 let signer1_pubkey = Pubkey::new_unique();
382 let signer0_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
383 let signer1_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
384 let keys = vec![(signer0_pubkey, true)];
385 let (config_keypair, config_account) = create_config_account(keys.clone());
386 let config_pubkey = config_keypair.pubkey();
387 let my_config = MyConfig::new(42);
388
389 let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
391 process_instruction(
392 &instruction.data,
393 vec![
394 (config_pubkey, config_account.clone()),
395 (signer1_pubkey, signer1_account),
396 ],
397 vec![
398 AccountMeta {
399 pubkey: config_pubkey,
400 is_signer: true,
401 is_writable: true,
402 },
403 AccountMeta {
404 pubkey: signer1_pubkey,
405 is_signer: true,
406 is_writable: false,
407 },
408 ],
409 Err(InstructionError::MissingRequiredSignature),
410 );
411
412 process_instruction(
414 &instruction.data,
415 vec![
416 (config_pubkey, config_account),
417 (signer0_pubkey, signer0_account),
418 ],
419 vec![
420 AccountMeta {
421 pubkey: config_pubkey,
422 is_signer: true,
423 is_writable: true,
424 },
425 AccountMeta {
426 pubkey: signer0_pubkey,
427 is_signer: false,
428 is_writable: false,
429 },
430 ],
431 Err(InstructionError::MissingRequiredSignature),
432 );
433 }
434
435 #[test]
436 fn test_config_updates() {
437 solana_logger::setup();
438 let pubkey = Pubkey::new_unique();
439 let signer0_pubkey = Pubkey::new_unique();
440 let signer1_pubkey = Pubkey::new_unique();
441 let signer2_pubkey = Pubkey::new_unique();
442 let signer0_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
443 let signer1_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
444 let signer2_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
445 let keys = vec![
446 (pubkey, false),
447 (signer0_pubkey, true),
448 (signer1_pubkey, true),
449 ];
450 let (config_keypair, config_account) = create_config_account(keys.clone());
451 let config_pubkey = config_keypair.pubkey();
452 let my_config = MyConfig::new(42);
453
454 let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
455 let accounts = process_instruction(
456 &instruction.data,
457 vec![
458 (config_pubkey, config_account),
459 (signer0_pubkey, signer0_account.clone()),
460 (signer1_pubkey, signer1_account.clone()),
461 ],
462 vec![
463 AccountMeta {
464 pubkey: config_pubkey,
465 is_signer: true,
466 is_writable: true,
467 },
468 AccountMeta {
469 pubkey: signer0_pubkey,
470 is_signer: true,
471 is_writable: false,
472 },
473 AccountMeta {
474 pubkey: signer1_pubkey,
475 is_signer: true,
476 is_writable: false,
477 },
478 ],
479 Ok(()),
480 );
481
482 let new_config = MyConfig::new(84);
484 let instruction =
485 config_instruction::store(&config_pubkey, false, keys.clone(), &new_config);
486 let accounts = process_instruction(
487 &instruction.data,
488 vec![
489 (config_pubkey, accounts[0].clone()),
490 (signer0_pubkey, signer0_account.clone()),
491 (signer1_pubkey, signer1_account.clone()),
492 ],
493 vec![
494 AccountMeta {
495 pubkey: config_pubkey,
496 is_signer: false,
497 is_writable: true,
498 },
499 AccountMeta {
500 pubkey: signer0_pubkey,
501 is_signer: true,
502 is_writable: false,
503 },
504 AccountMeta {
505 pubkey: signer1_pubkey,
506 is_signer: true,
507 is_writable: false,
508 },
509 ],
510 Ok(()),
511 );
512 let meta_data: ConfigKeys = deserialize(accounts[0].data()).unwrap();
513 assert_eq!(meta_data.keys, keys);
514 assert_eq!(
515 new_config,
516 MyConfig::deserialize(get_config_data(accounts[0].data()).unwrap()).unwrap()
517 );
518
519 let keys = vec![(pubkey, false), (signer0_pubkey, true)];
521 let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
522 process_instruction(
523 &instruction.data,
524 vec![
525 (config_pubkey, accounts[0].clone()),
526 (signer0_pubkey, signer0_account.clone()),
527 (signer1_pubkey, signer1_account),
528 ],
529 vec![
530 AccountMeta {
531 pubkey: config_pubkey,
532 is_signer: false,
533 is_writable: true,
534 },
535 AccountMeta {
536 pubkey: signer0_pubkey,
537 is_signer: true,
538 is_writable: false,
539 },
540 AccountMeta {
541 pubkey: signer1_pubkey,
542 is_signer: false,
543 is_writable: false,
544 },
545 ],
546 Err(InstructionError::MissingRequiredSignature),
547 );
548
549 let keys = vec![
551 (pubkey, false),
552 (signer0_pubkey, true),
553 (signer2_pubkey, true),
554 ];
555 let instruction = config_instruction::store(&config_pubkey, false, keys, &my_config);
556 process_instruction(
557 &instruction.data,
558 vec![
559 (config_pubkey, accounts[0].clone()),
560 (signer0_pubkey, signer0_account),
561 (signer2_pubkey, signer2_account),
562 ],
563 vec![
564 AccountMeta {
565 pubkey: config_pubkey,
566 is_signer: false,
567 is_writable: true,
568 },
569 AccountMeta {
570 pubkey: signer0_pubkey,
571 is_signer: true,
572 is_writable: false,
573 },
574 AccountMeta {
575 pubkey: signer2_pubkey,
576 is_signer: true,
577 is_writable: false,
578 },
579 ],
580 Err(InstructionError::MissingRequiredSignature),
581 );
582 }
583
584 #[test]
585 fn test_config_initialize_contains_duplicates_fails() {
586 solana_logger::setup();
587 let config_address = Pubkey::new_unique();
588 let signer0_pubkey = Pubkey::new_unique();
589 let signer0_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
590 let keys = vec![
591 (config_address, false),
592 (signer0_pubkey, true),
593 (signer0_pubkey, true),
594 ];
595 let (config_keypair, config_account) = create_config_account(keys.clone());
596 let config_pubkey = config_keypair.pubkey();
597 let my_config = MyConfig::new(42);
598
599 let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
601 process_instruction(
602 &instruction.data,
603 vec![
604 (config_pubkey, config_account),
605 (signer0_pubkey, signer0_account),
606 ],
607 vec![
608 AccountMeta {
609 pubkey: config_pubkey,
610 is_signer: true,
611 is_writable: true,
612 },
613 AccountMeta {
614 pubkey: signer0_pubkey,
615 is_signer: true,
616 is_writable: false,
617 },
618 AccountMeta {
619 pubkey: signer0_pubkey,
620 is_signer: true,
621 is_writable: false,
622 },
623 ],
624 Err(InstructionError::InvalidArgument),
625 );
626 }
627
628 #[test]
629 fn test_config_update_contains_duplicates_fails() {
630 solana_logger::setup();
631 let config_address = Pubkey::new_unique();
632 let signer0_pubkey = Pubkey::new_unique();
633 let signer1_pubkey = Pubkey::new_unique();
634 let signer0_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
635 let signer1_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
636 let keys = vec![
637 (config_address, false),
638 (signer0_pubkey, true),
639 (signer1_pubkey, true),
640 ];
641 let (config_keypair, config_account) = create_config_account(keys.clone());
642 let config_pubkey = config_keypair.pubkey();
643 let my_config = MyConfig::new(42);
644
645 let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
646 let accounts = process_instruction(
647 &instruction.data,
648 vec![
649 (config_pubkey, config_account),
650 (signer0_pubkey, signer0_account.clone()),
651 (signer1_pubkey, signer1_account),
652 ],
653 vec![
654 AccountMeta {
655 pubkey: config_pubkey,
656 is_signer: true,
657 is_writable: true,
658 },
659 AccountMeta {
660 pubkey: signer0_pubkey,
661 is_signer: true,
662 is_writable: false,
663 },
664 AccountMeta {
665 pubkey: signer1_pubkey,
666 is_signer: true,
667 is_writable: false,
668 },
669 ],
670 Ok(()),
671 );
672
673 let new_config = MyConfig::new(84);
675 let dupe_keys = vec![
676 (config_address, false),
677 (signer0_pubkey, true),
678 (signer0_pubkey, true),
679 ];
680 let instruction = config_instruction::store(&config_pubkey, false, dupe_keys, &new_config);
681 process_instruction(
682 &instruction.data,
683 vec![
684 (config_pubkey, accounts[0].clone()),
685 (signer0_pubkey, signer0_account),
686 ],
687 vec![
688 AccountMeta {
689 pubkey: config_pubkey,
690 is_signer: true,
691 is_writable: true,
692 },
693 AccountMeta {
694 pubkey: signer0_pubkey,
695 is_signer: true,
696 is_writable: false,
697 },
698 AccountMeta {
699 pubkey: signer0_pubkey,
700 is_signer: true,
701 is_writable: false,
702 },
703 ],
704 Err(InstructionError::InvalidArgument),
705 );
706 }
707
708 #[test]
709 fn test_config_updates_requiring_config() {
710 solana_logger::setup();
711 let pubkey = Pubkey::new_unique();
712 let signer0_pubkey = Pubkey::new_unique();
713 let signer0_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
714 let keys = vec![
715 (pubkey, false),
716 (signer0_pubkey, true),
717 (signer0_pubkey, true),
718 ]; let (config_keypair, config_account) = create_config_account(keys);
720 let config_pubkey = config_keypair.pubkey();
721 let my_config = MyConfig::new(42);
722 let keys = vec![
723 (pubkey, false),
724 (signer0_pubkey, true),
725 (config_keypair.pubkey(), true),
726 ];
727
728 let instruction = config_instruction::store(&config_pubkey, true, keys.clone(), &my_config);
729 let accounts = process_instruction(
730 &instruction.data,
731 vec![
732 (config_pubkey, config_account),
733 (signer0_pubkey, signer0_account.clone()),
734 ],
735 vec![
736 AccountMeta {
737 pubkey: config_pubkey,
738 is_signer: true,
739 is_writable: true,
740 },
741 AccountMeta {
742 pubkey: signer0_pubkey,
743 is_signer: true,
744 is_writable: false,
745 },
746 ],
747 Ok(()),
748 );
749
750 let new_config = MyConfig::new(84);
752 let instruction =
753 config_instruction::store(&config_pubkey, true, keys.clone(), &new_config);
754 let accounts = process_instruction(
755 &instruction.data,
756 vec![
757 (config_pubkey, accounts[0].clone()),
758 (signer0_pubkey, signer0_account),
759 ],
760 vec![
761 AccountMeta {
762 pubkey: config_pubkey,
763 is_signer: true,
764 is_writable: true,
765 },
766 AccountMeta {
767 pubkey: signer0_pubkey,
768 is_signer: true,
769 is_writable: false,
770 },
771 ],
772 Ok(()),
773 );
774 let meta_data: ConfigKeys = deserialize(accounts[0].data()).unwrap();
775 assert_eq!(meta_data.keys, keys);
776 assert_eq!(
777 new_config,
778 MyConfig::deserialize(get_config_data(accounts[0].data()).unwrap()).unwrap()
779 );
780
781 let keys = vec![(pubkey, false), (config_keypair.pubkey(), true)];
783 let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
784 process_instruction(
785 &instruction.data,
786 vec![(config_pubkey, accounts[0].clone())],
787 vec![AccountMeta {
788 pubkey: config_pubkey,
789 is_signer: true,
790 is_writable: true,
791 }],
792 Err(InstructionError::MissingRequiredSignature),
793 );
794 }
795
796 #[test]
797 fn test_config_initialize_no_panic() {
798 let from_pubkey = Pubkey::new_unique();
799 let config_pubkey = Pubkey::new_unique();
800 let (_, _config_account) = create_config_account(vec![]);
801 let instructions =
802 config_instruction::create_account::<MyConfig>(&from_pubkey, &config_pubkey, 1, vec![]);
803 process_instruction(
804 &instructions[1].data,
805 Vec::new(),
806 Vec::new(),
807 Err(InstructionError::NotEnoughAccountKeys),
808 );
809 }
810
811 #[test]
812 fn test_config_bad_owner() {
813 let from_pubkey = Pubkey::new_unique();
814 let config_pubkey = Pubkey::new_unique();
815 let new_config = MyConfig::new(84);
816 let signer0_pubkey = Pubkey::new_unique();
817 let signer0_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
818 let config_account = AccountSharedData::new(0, 0, &Pubkey::new_unique());
819 let (_, _config_account) = create_config_account(vec![]);
820 let keys = vec![
821 (from_pubkey, false),
822 (signer0_pubkey, true),
823 (config_pubkey, true),
824 ];
825
826 let instruction = config_instruction::store(&config_pubkey, true, keys, &new_config);
827 process_instruction(
828 &instruction.data,
829 vec![
830 (config_pubkey, config_account),
831 (signer0_pubkey, signer0_account),
832 ],
833 vec![
834 AccountMeta {
835 pubkey: config_pubkey,
836 is_signer: true,
837 is_writable: true,
838 },
839 AccountMeta {
840 pubkey: signer0_pubkey,
841 is_signer: true,
842 is_writable: false,
843 },
844 ],
845 Err(InstructionError::InvalidAccountOwner),
846 );
847 }
848}