1use {
2 crate::system_instruction::{
3 advance_nonce_account, authorize_nonce_account, initialize_nonce_account,
4 withdraw_nonce_account,
5 },
6 log::*,
7 solana_bincode::limited_deserialize,
8 solana_instruction_error::InstructionError,
9 solana_nonce as nonce,
10 solana_program_runtime::{
11 declare_process_instruction, invoke_context::InvokeContext,
12 sysvar_cache::get_sysvar_with_account_check,
13 },
14 solana_pubkey::Pubkey,
15 solana_sdk_ids::system_program,
16 solana_svm_log_collector::ic_msg,
17 solana_system_interface::{
18 MAX_PERMITTED_DATA_LENGTH, error::SystemError, instruction::SystemInstruction,
19 },
20 solana_transaction_context::{
21 IndexOfAccount, instruction::InstructionContext,
22 instruction_accounts::BorrowedInstructionAccount,
23 },
24 std::collections::HashSet,
25};
26
27#[derive(PartialEq, Eq, Default, Debug)]
30struct Address {
31 address: Pubkey,
32 base: Option<Pubkey>,
33}
34
35impl Address {
36 fn is_signer(&self, signers: &HashSet<Pubkey>) -> bool {
37 if let Some(base) = self.base {
38 signers.contains(&base)
39 } else {
40 signers.contains(&self.address)
41 }
42 }
43 fn create(
44 address: &Pubkey,
45 with_seed: Option<(&Pubkey, &str, &Pubkey)>,
46 invoke_context: &InvokeContext,
47 ) -> Result<Self, InstructionError> {
48 let base = if let Some((base, seed, owner)) = with_seed {
49 let address_with_seed =
52 Pubkey::create_with_seed(base, seed, owner).map_err(|e| e as u64)?;
53 if *address != address_with_seed {
55 ic_msg!(
56 invoke_context,
57 "Create: address {} does not match derived address {}",
58 address,
59 address_with_seed
60 );
61 return Err(SystemError::AddressWithSeedMismatch.into());
62 }
63 Some(*base)
64 } else {
65 None
66 };
67
68 Ok(Self {
69 address: *address,
70 base,
71 })
72 }
73}
74
75fn allocate(
76 account: &mut BorrowedInstructionAccount,
77 address: &Address,
78 space: u64,
79 signers: &HashSet<Pubkey>,
80 invoke_context: &InvokeContext,
81) -> Result<(), InstructionError> {
82 if !address.is_signer(signers) {
83 ic_msg!(
84 invoke_context,
85 "Allocate: 'to' account {:?} must sign",
86 address
87 );
88 return Err(InstructionError::MissingRequiredSignature);
89 }
90
91 if !account.get_data().is_empty() || !system_program::check_id(account.get_owner()) {
94 ic_msg!(
95 invoke_context,
96 "Allocate: account {:?} already in use",
97 address
98 );
99 return Err(SystemError::AccountAlreadyInUse.into());
100 }
101
102 if space > MAX_PERMITTED_DATA_LENGTH {
103 ic_msg!(
104 invoke_context,
105 "Allocate: requested {}, max allowed {}",
106 space,
107 MAX_PERMITTED_DATA_LENGTH
108 );
109 return Err(SystemError::InvalidAccountDataLength.into());
110 }
111
112 account.set_data_length(space as usize)?;
113
114 Ok(())
115}
116
117fn assign(
118 account: &mut BorrowedInstructionAccount,
119 address: &Address,
120 owner: &Pubkey,
121 signers: &HashSet<Pubkey>,
122 invoke_context: &InvokeContext,
123) -> Result<(), InstructionError> {
124 if account.get_owner() == owner {
126 return Ok(());
127 }
128
129 if !address.is_signer(signers) {
130 ic_msg!(invoke_context, "Assign: account {:?} must sign", address);
131 return Err(InstructionError::MissingRequiredSignature);
132 }
133
134 account.set_owner(&owner.to_bytes())
135}
136
137fn allocate_and_assign(
138 to: &mut BorrowedInstructionAccount,
139 to_address: &Address,
140 space: u64,
141 owner: &Pubkey,
142 signers: &HashSet<Pubkey>,
143 invoke_context: &InvokeContext,
144) -> Result<(), InstructionError> {
145 allocate(to, to_address, space, signers, invoke_context)?;
146 assign(to, to_address, owner, signers, invoke_context)
147}
148
149#[allow(clippy::too_many_arguments)]
150fn create_account(
151 from_account_index: IndexOfAccount,
152 to_account_index: IndexOfAccount,
153 to_address: &Address,
154 lamports: u64,
155 space: u64,
156 owner: &Pubkey,
157 signers: &HashSet<Pubkey>,
158 invoke_context: &InvokeContext,
159 instruction_context: &InstructionContext,
160) -> Result<(), InstructionError> {
161 {
163 let mut to = instruction_context.try_borrow_instruction_account(to_account_index)?;
164 if to.get_lamports() > 0 {
165 ic_msg!(
166 invoke_context,
167 "Create Account: account {:?} already in use",
168 to_address
169 );
170 return Err(SystemError::AccountAlreadyInUse.into());
171 }
172
173 allocate_and_assign(&mut to, to_address, space, owner, signers, invoke_context)?;
174 }
175 transfer(
176 from_account_index,
177 to_account_index,
178 lamports,
179 invoke_context,
180 instruction_context,
181 )
182}
183
184#[allow(clippy::too_many_arguments)]
188fn create_account_allow_prefund(
189 to_account_index: IndexOfAccount,
190 to_address: &Address,
191 from_and_lamports: Option<(IndexOfAccount, u64)>,
192 space: u64,
193 owner: &Pubkey,
194 signers: &HashSet<Pubkey>,
195 invoke_context: &InvokeContext,
196 instruction_context: &InstructionContext,
197) -> Result<(), InstructionError> {
198 {
199 let mut to = instruction_context.try_borrow_instruction_account(to_account_index)?;
200 allocate_and_assign(&mut to, to_address, space, owner, signers, invoke_context)?;
201 }
202 if let Some((from_account_index, lamports)) = from_and_lamports
203 && lamports > 0
204 {
205 transfer(
206 from_account_index,
207 to_account_index,
208 lamports,
209 invoke_context,
210 instruction_context,
211 )?;
212 }
213 Ok(())
214}
215
216fn transfer_verified(
217 from_account_index: IndexOfAccount,
218 to_account_index: IndexOfAccount,
219 lamports: u64,
220 invoke_context: &InvokeContext,
221 instruction_context: &InstructionContext,
222) -> Result<(), InstructionError> {
223 let mut from = instruction_context.try_borrow_instruction_account(from_account_index)?;
224 if !from.get_data().is_empty() {
225 ic_msg!(invoke_context, "Transfer: `from` must not carry data");
226 return Err(InstructionError::InvalidArgument);
227 }
228 if lamports > from.get_lamports() {
229 ic_msg!(
230 invoke_context,
231 "Transfer: insufficient lamports {}, need {}",
232 from.get_lamports(),
233 lamports
234 );
235 return Err(SystemError::ResultWithNegativeLamports.into());
236 }
237
238 from.checked_sub_lamports(lamports)?;
239 drop(from);
240 let mut to = instruction_context.try_borrow_instruction_account(to_account_index)?;
241 to.checked_add_lamports(lamports)?;
242 Ok(())
243}
244
245fn transfer(
246 from_account_index: IndexOfAccount,
247 to_account_index: IndexOfAccount,
248 lamports: u64,
249 invoke_context: &InvokeContext,
250 instruction_context: &InstructionContext,
251) -> Result<(), InstructionError> {
252 if !instruction_context.is_instruction_account_signer(from_account_index)? {
253 ic_msg!(
254 invoke_context,
255 "Transfer: `from` account {} must sign",
256 instruction_context.get_key_of_instruction_account(from_account_index)?,
257 );
258 return Err(InstructionError::MissingRequiredSignature);
259 }
260
261 transfer_verified(
262 from_account_index,
263 to_account_index,
264 lamports,
265 invoke_context,
266 instruction_context,
267 )
268}
269
270fn transfer_with_seed(
271 from_account_index: IndexOfAccount,
272 from_base_account_index: IndexOfAccount,
273 from_seed: &str,
274 from_owner: &Pubkey,
275 to_account_index: IndexOfAccount,
276 lamports: u64,
277 invoke_context: &InvokeContext,
278 instruction_context: &InstructionContext,
279) -> Result<(), InstructionError> {
280 if !instruction_context.is_instruction_account_signer(from_base_account_index)? {
281 ic_msg!(
282 invoke_context,
283 "Transfer: 'from' account {:?} must sign",
284 instruction_context.get_key_of_instruction_account(from_base_account_index,)?,
285 );
286 return Err(InstructionError::MissingRequiredSignature);
287 }
288 let address_from_seed = Pubkey::create_with_seed(
291 instruction_context.get_key_of_instruction_account(from_base_account_index)?,
292 from_seed,
293 from_owner,
294 )
295 .map_err(|e| e as u64)?;
296
297 let from_key = instruction_context.get_key_of_instruction_account(from_account_index)?;
298 if *from_key != address_from_seed {
299 ic_msg!(
300 invoke_context,
301 "Transfer: 'from' address {} does not match derived address {}",
302 from_key,
303 address_from_seed
304 );
305 return Err(SystemError::AddressWithSeedMismatch.into());
306 }
307
308 transfer_verified(
309 from_account_index,
310 to_account_index,
311 lamports,
312 invoke_context,
313 instruction_context,
314 )
315}
316
317pub const DEFAULT_COMPUTE_UNITS: u64 = 150;
318
319declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context| {
320 let transaction_context = &invoke_context.transaction_context;
321 let instruction_context = transaction_context.get_current_instruction_context()?;
322 let instruction_data = instruction_context.get_instruction_data();
323 let instruction =
324 limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)?;
325
326 trace!("process_instruction: {instruction:?}");
327
328 let signers = instruction_context.get_signers()?;
329 match instruction {
330 SystemInstruction::CreateAccount {
331 lamports,
332 space,
333 owner,
334 } => {
335 instruction_context.check_number_of_instruction_accounts(2)?;
336 let to_address = Address::create(
337 instruction_context.get_key_of_instruction_account(1)?,
338 None,
339 invoke_context,
340 )?;
341 create_account(
342 0,
343 1,
344 &to_address,
345 lamports,
346 space,
347 &owner,
348 &signers,
349 invoke_context,
350 &instruction_context,
351 )
352 }
353
354 SystemInstruction::CreateAccountWithSeed {
355 base,
356 seed,
357 lamports,
358 space,
359 owner,
360 } => {
361 instruction_context.check_number_of_instruction_accounts(2)?;
362 let to_address = Address::create(
363 instruction_context.get_key_of_instruction_account(1)?,
364 Some((&base, &seed, &owner)),
365 invoke_context,
366 )?;
367 create_account(
368 0,
369 1,
370 &to_address,
371 lamports,
372 space,
373 &owner,
374 &signers,
375 invoke_context,
376 &instruction_context,
377 )
378 }
379 SystemInstruction::Assign { owner } => {
380 instruction_context.check_number_of_instruction_accounts(1)?;
381 let mut account = instruction_context.try_borrow_instruction_account(0)?;
382 let address = Address::create(
383 instruction_context.get_key_of_instruction_account(0)?,
384 None,
385 invoke_context,
386 )?;
387 assign(&mut account, &address, &owner, &signers, invoke_context)
388 }
389 SystemInstruction::Transfer { lamports } => {
390 instruction_context.check_number_of_instruction_accounts(2)?;
391 transfer(0, 1, lamports, invoke_context, &instruction_context)
392 }
393 SystemInstruction::TransferWithSeed {
394 lamports,
395 from_seed,
396 from_owner,
397 } => {
398 instruction_context.check_number_of_instruction_accounts(3)?;
399 transfer_with_seed(
400 0,
401 1,
402 &from_seed,
403 &from_owner,
404 2,
405 lamports,
406 invoke_context,
407 &instruction_context,
408 )
409 }
410 SystemInstruction::AdvanceNonceAccount => {
411 instruction_context.check_number_of_instruction_accounts(1)?;
412 let mut me = instruction_context.try_borrow_instruction_account(0)?;
413 #[allow(deprecated)]
414 let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
415 invoke_context,
416 &instruction_context,
417 1,
418 )?;
419 if recent_blockhashes.is_empty() {
420 ic_msg!(
421 invoke_context,
422 "Advance nonce account: recent blockhash list is empty",
423 );
424 return Err(SystemError::NonceNoRecentBlockhashes.into());
425 }
426 advance_nonce_account(&mut me, &signers, invoke_context)
427 }
428 SystemInstruction::WithdrawNonceAccount(lamports) => {
429 instruction_context.check_number_of_instruction_accounts(2)?;
430 #[allow(deprecated)]
431 let _recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
432 invoke_context,
433 &instruction_context,
434 2,
435 )?;
436 let rent =
437 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 3)?;
438 withdraw_nonce_account(
439 0,
440 lamports,
441 1,
442 &rent,
443 &signers,
444 invoke_context,
445 &instruction_context,
446 )
447 }
448 SystemInstruction::InitializeNonceAccount(authorized) => {
449 instruction_context.check_number_of_instruction_accounts(1)?;
450 let mut me = instruction_context.try_borrow_instruction_account(0)?;
451 #[allow(deprecated)]
452 let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
453 invoke_context,
454 &instruction_context,
455 1,
456 )?;
457 if recent_blockhashes.is_empty() {
458 ic_msg!(
459 invoke_context,
460 "Initialize nonce account: recent blockhash list is empty",
461 );
462 return Err(SystemError::NonceNoRecentBlockhashes.into());
463 }
464 let rent =
465 get_sysvar_with_account_check::rent(invoke_context, &instruction_context, 2)?;
466 initialize_nonce_account(&mut me, &authorized, &rent, invoke_context)
467 }
468 SystemInstruction::AuthorizeNonceAccount(nonce_authority) => {
469 instruction_context.check_number_of_instruction_accounts(1)?;
470 let mut me = instruction_context.try_borrow_instruction_account(0)?;
471 authorize_nonce_account(&mut me, &nonce_authority, &signers, invoke_context)
472 }
473 SystemInstruction::UpgradeNonceAccount => {
474 instruction_context.check_number_of_instruction_accounts(1)?;
475 let mut nonce_account = instruction_context.try_borrow_instruction_account(0)?;
476 if !system_program::check_id(nonce_account.get_owner()) {
477 return Err(InstructionError::InvalidAccountOwner);
478 }
479 if !nonce_account.is_writable() {
480 return Err(InstructionError::InvalidArgument);
481 }
482 let nonce_versions: nonce::versions::Versions = nonce_account.get_state()?;
483 match nonce_versions.upgrade() {
484 None => Err(InstructionError::InvalidArgument),
485 Some(nonce_versions) => nonce_account.set_state(&nonce_versions),
486 }
487 }
488 SystemInstruction::Allocate { space } => {
489 instruction_context.check_number_of_instruction_accounts(1)?;
490 let mut account = instruction_context.try_borrow_instruction_account(0)?;
491 let address = Address::create(
492 instruction_context.get_key_of_instruction_account(0)?,
493 None,
494 invoke_context,
495 )?;
496 allocate(&mut account, &address, space, &signers, invoke_context)
497 }
498 SystemInstruction::AllocateWithSeed {
499 base,
500 seed,
501 space,
502 owner,
503 } => {
504 instruction_context.check_number_of_instruction_accounts(1)?;
505 let mut account = instruction_context.try_borrow_instruction_account(0)?;
506 let address = Address::create(
507 instruction_context.get_key_of_instruction_account(0)?,
508 Some((&base, &seed, &owner)),
509 invoke_context,
510 )?;
511 allocate_and_assign(
512 &mut account,
513 &address,
514 space,
515 &owner,
516 &signers,
517 invoke_context,
518 )
519 }
520 SystemInstruction::AssignWithSeed { base, seed, owner } => {
521 instruction_context.check_number_of_instruction_accounts(1)?;
522 let mut account = instruction_context.try_borrow_instruction_account(0)?;
523 let address = Address::create(
524 instruction_context.get_key_of_instruction_account(0)?,
525 Some((&base, &seed, &owner)),
526 invoke_context,
527 )?;
528 assign(&mut account, &address, &owner, &signers, invoke_context)
529 }
530 SystemInstruction::CreateAccountAllowPrefund {
531 lamports,
532 space,
533 owner,
534 } => {
535 if !invoke_context
536 .get_feature_set()
537 .create_account_allow_prefund
538 {
539 return Err(InstructionError::InvalidInstructionData);
540 }
541 let from_and_lamports = if lamports > 0 {
542 instruction_context.check_number_of_instruction_accounts(2)?;
543 Some((1, lamports))
544 } else {
545 instruction_context.check_number_of_instruction_accounts(1)?;
546 None
547 };
548 let to_address = Address::create(
549 instruction_context.get_key_of_instruction_account(0)?,
550 None,
551 invoke_context,
552 )?;
553 create_account_allow_prefund(
554 0,
555 &to_address,
556 from_and_lamports,
557 space,
558 &owner,
559 &signers,
560 invoke_context,
561 &instruction_context,
562 )
563 }
564 }
565});
566
567#[cfg(test)]
568mod tests {
569 use {
570 super::*,
571 bincode::serialize,
572 solana_nonce_account::{SystemAccountKind, get_system_account_kind},
573 solana_program_runtime::{
574 invoke_context::mock_process_instruction,
575 solana_sbpf::program::BuiltinFunctionDefinition, with_mock_invoke_context,
576 },
577 std::collections::BinaryHeap,
578 };
579 #[allow(deprecated)]
580 use {
581 solana_account::{
582 Account, AccountSharedData, ReadableAccount, WritableAccount,
583 state_traits::StateMutWincode as _,
584 },
585 solana_fee_calculator::FeeCalculator,
586 solana_hash::Hash,
587 solana_instruction::{AccountMeta, Instruction},
588 solana_instruction_error::InstructionError,
589 solana_nonce::{
590 self as nonce,
591 state::{Data as NonceData, DurableNonce, State as NonceState},
592 versions::Versions as NonceVersions,
593 },
594 solana_nonce_account as nonce_account,
595 solana_sha256_hasher::hash,
596 solana_system_interface::{instruction as system_instruction, program as system_program},
597 solana_sysvar::{
598 self as sysvar,
599 recent_blockhashes::{IntoIterSorted, IterItem, MAX_ENTRIES, RecentBlockhashes},
600 rent::Rent,
601 },
602 solana_sysvar_id::SysvarId,
603 };
604
605 fn create_sysvar_account<T>(value: &T) -> AccountSharedData
606 where
607 T: wincode::Serialize<Src = T> + SysvarId,
608 {
609 let serialized_len = wincode::serialized_size(value).unwrap() as usize;
610 let canonical_data_len = match T::id() {
611 sysvar::recent_blockhashes::ID => sysvar::recent_blockhashes::SIZE,
612 sysvar::rent::ID => solana_rent::SIZE,
613 id => panic!("unsupported sysvar: {id}"),
614 };
615 let required_data_len = canonical_data_len.max(serialized_len);
616 let mut account =
617 AccountSharedData::new(1, required_data_len, &solana_sdk_ids::sysvar::id());
618 wincode::serialize_into(account.data_as_mut_slice(), value).unwrap();
619 account
620 }
621
622 impl From<Pubkey> for Address {
623 fn from(address: Pubkey) -> Self {
624 Self {
625 address,
626 base: None,
627 }
628 }
629 }
630
631 fn process_instruction(
632 instruction_data: &[u8],
633 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
634 instruction_accounts: Vec<AccountMeta>,
635 expected_result: Result<(), InstructionError>,
636 ) -> Vec<AccountSharedData> {
637 mock_process_instruction(
638 &system_program::id(),
639 instruction_data,
640 transaction_accounts,
641 instruction_accounts,
642 expected_result,
643 Entrypoint::register,
644 |_invoke_context| {},
645 |_invoke_context| {},
646 )
647 }
648
649 fn create_default_account() -> AccountSharedData {
650 AccountSharedData::new(0, 0, &Pubkey::new_unique())
651 }
652 #[allow(deprecated)]
653 fn create_recent_blockhashes_account_for_test<'a, I>(
654 recent_blockhash_iter: I,
655 ) -> AccountSharedData
656 where
657 I: IntoIterator<Item = IterItem<'a>>,
658 {
659 let sorted = BinaryHeap::from_iter(recent_blockhash_iter);
660 let sorted_iter = IntoIterSorted::new(sorted);
661 let recent_blockhash_iter = sorted_iter.take(MAX_ENTRIES);
662 let recent_blockhashes: RecentBlockhashes = recent_blockhash_iter.collect();
663 create_sysvar_account(&recent_blockhashes)
664 }
665 fn create_default_recent_blockhashes_account() -> AccountSharedData {
666 #[allow(deprecated)]
667 create_recent_blockhashes_account_for_test(vec![
668 IterItem(0u64, &Hash::default(), 0);
669 sysvar::recent_blockhashes::MAX_ENTRIES
670 ])
671 }
672 fn create_default_rent_account() -> AccountSharedData {
673 create_sysvar_account(&Rent::free())
674 }
675
676 #[test]
677 fn test_create_account() {
678 let new_owner = Pubkey::from([9; 32]);
679 let from = Pubkey::new_unique();
680 let to = Pubkey::new_unique();
681 let from_account = AccountSharedData::new(100, 0, &system_program::id());
682 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
683
684 let accounts = process_instruction(
685 &bincode::serialize(&SystemInstruction::CreateAccount {
686 lamports: 50,
687 space: 2,
688 owner: new_owner,
689 })
690 .unwrap(),
691 vec![(from, from_account), (to, to_account)],
692 vec![
693 AccountMeta {
694 pubkey: from,
695 is_signer: true,
696 is_writable: true,
697 },
698 AccountMeta {
699 pubkey: to,
700 is_signer: true,
701 is_writable: true,
702 },
703 ],
704 Ok(()),
705 );
706 assert_eq!(accounts[0].lamports(), 50);
707 assert_eq!(accounts[1].lamports(), 50);
708 assert_eq!(accounts[1].owner(), &new_owner);
709 assert_eq!(accounts[1].data(), &[0, 0]);
710 }
711
712 #[test]
713 fn test_create_account_with_seed() {
714 let new_owner = Pubkey::from([9; 32]);
715 let from = Pubkey::new_unique();
716 let seed = "shiny pepper";
717 let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
718 let from_account = AccountSharedData::new(100, 0, &system_program::id());
719 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
720
721 let accounts = process_instruction(
722 &bincode::serialize(&SystemInstruction::CreateAccountWithSeed {
723 base: from,
724 seed: seed.to_string(),
725 lamports: 50,
726 space: 2,
727 owner: new_owner,
728 })
729 .unwrap(),
730 vec![(from, from_account), (to, to_account)],
731 vec![
732 AccountMeta {
733 pubkey: from,
734 is_signer: true,
735 is_writable: true,
736 },
737 AccountMeta {
738 pubkey: to,
739 is_signer: true,
740 is_writable: true,
741 },
742 ],
743 Ok(()),
744 );
745 assert_eq!(accounts[0].lamports(), 50);
746 assert_eq!(accounts[1].lamports(), 50);
747 assert_eq!(accounts[1].owner(), &new_owner);
748 assert_eq!(accounts[1].data(), &[0, 0]);
749 }
750
751 #[test]
752 fn test_create_account_with_seed_separate_base_account() {
753 let new_owner = Pubkey::from([9; 32]);
754 let from = Pubkey::new_unique();
755 let base = Pubkey::new_unique();
756 let seed = "shiny pepper";
757 let to = Pubkey::create_with_seed(&base, seed, &new_owner).unwrap();
758 let from_account = AccountSharedData::new(100, 0, &system_program::id());
759 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
760 let base_account = AccountSharedData::new(0, 0, &Pubkey::default());
761
762 let accounts = process_instruction(
763 &bincode::serialize(&SystemInstruction::CreateAccountWithSeed {
764 base,
765 seed: seed.to_string(),
766 lamports: 50,
767 space: 2,
768 owner: new_owner,
769 })
770 .unwrap(),
771 vec![(from, from_account), (to, to_account), (base, base_account)],
772 vec![
773 AccountMeta {
774 pubkey: from,
775 is_signer: true,
776 is_writable: true,
777 },
778 AccountMeta {
779 pubkey: to,
780 is_signer: false,
781 is_writable: true,
782 },
783 AccountMeta {
784 pubkey: base,
785 is_signer: true,
786 is_writable: false,
787 },
788 ],
789 Ok(()),
790 );
791 assert_eq!(accounts[0].lamports(), 50);
792 assert_eq!(accounts[1].lamports(), 50);
793 assert_eq!(accounts[1].owner(), &new_owner);
794 assert_eq!(accounts[1].data(), &[0, 0]);
795 }
796
797 #[test]
798 fn test_address_create_with_seed_mismatch() {
799 with_mock_invoke_context!(invoke_context, transaction_context, Vec::new());
800 let from = Pubkey::new_unique();
801 let seed = "dull boy";
802 let to = Pubkey::new_unique();
803 let owner = Pubkey::new_unique();
804
805 assert_eq!(
806 Address::create(&to, Some((&from, seed, &owner)), &invoke_context),
807 Err(SystemError::AddressWithSeedMismatch.into())
808 );
809 }
810
811 #[test]
812 fn test_create_account_with_seed_missing_sig() {
813 let new_owner = Pubkey::from([9; 32]);
814 let from = Pubkey::new_unique();
815 let seed = "dull boy";
816 let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
817 let from_account = AccountSharedData::new(100, 0, &system_program::id());
818 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
819
820 let accounts = process_instruction(
821 &bincode::serialize(&SystemInstruction::CreateAccount {
822 lamports: 50,
823 space: 2,
824 owner: new_owner,
825 })
826 .unwrap(),
827 vec![(from, from_account), (to, to_account)],
828 vec![
829 AccountMeta {
830 pubkey: from,
831 is_signer: true,
832 is_writable: false,
833 },
834 AccountMeta {
835 pubkey: to,
836 is_signer: false,
837 is_writable: false,
838 },
839 ],
840 Err(InstructionError::MissingRequiredSignature),
841 );
842 assert_eq!(accounts[0].lamports(), 100);
843 assert_eq!(accounts[1], AccountSharedData::default());
844 }
845
846 #[test]
847 fn test_create_with_zero_lamports() {
848 let new_owner = Pubkey::from([9; 32]);
850 let from = Pubkey::new_unique();
851 let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique()); let to = Pubkey::new_unique();
853 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
854
855 let accounts = process_instruction(
856 &bincode::serialize(&SystemInstruction::CreateAccount {
857 lamports: 0,
858 space: 2,
859 owner: new_owner,
860 })
861 .unwrap(),
862 vec![(from, from_account), (to, to_account)],
863 vec![
864 AccountMeta {
865 pubkey: from,
866 is_signer: true,
867 is_writable: true,
868 },
869 AccountMeta {
870 pubkey: to,
871 is_signer: true,
872 is_writable: true,
873 },
874 ],
875 Ok(()),
876 );
877 assert_eq!(accounts[0].lamports(), 100);
878 assert_eq!(accounts[1].lamports(), 0);
879 assert_eq!(*accounts[1].owner(), new_owner);
880 assert_eq!(accounts[1].data(), &[0, 0]);
881 }
882
883 #[test]
884 fn test_create_negative_lamports() {
885 let new_owner = Pubkey::from([9; 32]);
887 let from = Pubkey::new_unique();
888 let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique());
889 let to = Pubkey::new_unique();
890 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
891
892 process_instruction(
893 &bincode::serialize(&SystemInstruction::CreateAccount {
894 lamports: 150,
895 space: 2,
896 owner: new_owner,
897 })
898 .unwrap(),
899 vec![(from, from_account), (to, to_account)],
900 vec![
901 AccountMeta {
902 pubkey: from,
903 is_signer: true,
904 is_writable: true,
905 },
906 AccountMeta {
907 pubkey: to,
908 is_signer: true,
909 is_writable: true,
910 },
911 ],
912 Err(SystemError::ResultWithNegativeLamports.into()),
913 );
914 }
915
916 #[test]
917 fn test_request_more_than_allowed_data_length() {
918 let from = Pubkey::new_unique();
919 let from_account = AccountSharedData::new(100, 0, &system_program::id());
920 let to = Pubkey::new_unique();
921 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
922 let instruction_accounts = vec![
923 AccountMeta {
924 pubkey: from,
925 is_signer: true,
926 is_writable: true,
927 },
928 AccountMeta {
929 pubkey: to,
930 is_signer: true,
931 is_writable: true,
932 },
933 ];
934
935 process_instruction(
937 &bincode::serialize(&SystemInstruction::CreateAccount {
938 lamports: 50,
939 space: MAX_PERMITTED_DATA_LENGTH + 1,
940 owner: system_program::id(),
941 })
942 .unwrap(),
943 vec![(from, from_account.clone()), (to, to_account.clone())],
944 instruction_accounts.clone(),
945 Err(SystemError::InvalidAccountDataLength.into()),
946 );
947
948 let accounts = process_instruction(
950 &bincode::serialize(&SystemInstruction::CreateAccount {
951 lamports: 50,
952 space: MAX_PERMITTED_DATA_LENGTH,
953 owner: system_program::id(),
954 })
955 .unwrap(),
956 vec![(from, from_account), (to, to_account)],
957 instruction_accounts,
958 Ok(()),
959 );
960 assert_eq!(accounts[1].lamports(), 50);
961 assert_eq!(accounts[1].data().len() as u64, MAX_PERMITTED_DATA_LENGTH);
962 }
963
964 #[test]
965 fn test_create_already_in_use() {
966 let new_owner = Pubkey::from([9; 32]);
967 let from = Pubkey::new_unique();
968 let from_account = AccountSharedData::new(100, 0, &system_program::id());
969 let owned_key = Pubkey::new_unique();
970
971 let original_program_owner = Pubkey::from([5; 32]);
973 let owned_account = AccountSharedData::new(0, 0, &original_program_owner);
974 let unchanged_account = owned_account.clone();
975 let accounts = process_instruction(
976 &bincode::serialize(&SystemInstruction::CreateAccount {
977 lamports: 50,
978 space: 2,
979 owner: new_owner,
980 })
981 .unwrap(),
982 vec![(from, from_account.clone()), (owned_key, owned_account)],
983 vec![
984 AccountMeta {
985 pubkey: from,
986 is_signer: true,
987 is_writable: false,
988 },
989 AccountMeta {
990 pubkey: owned_key,
991 is_signer: true,
992 is_writable: false,
993 },
994 ],
995 Err(SystemError::AccountAlreadyInUse.into()),
996 );
997 assert_eq!(accounts[0].lamports(), 100);
998 assert_eq!(accounts[1], unchanged_account);
999
1000 let owned_account = AccountSharedData::new(0, 1, &Pubkey::default());
1002 let unchanged_account = owned_account.clone();
1003 let accounts = process_instruction(
1004 &bincode::serialize(&SystemInstruction::CreateAccount {
1005 lamports: 50,
1006 space: 2,
1007 owner: new_owner,
1008 })
1009 .unwrap(),
1010 vec![(from, from_account.clone()), (owned_key, owned_account)],
1011 vec![
1012 AccountMeta {
1013 pubkey: from,
1014 is_signer: true,
1015 is_writable: false,
1016 },
1017 AccountMeta {
1018 pubkey: owned_key,
1019 is_signer: true,
1020 is_writable: false,
1021 },
1022 ],
1023 Err(SystemError::AccountAlreadyInUse.into()),
1024 );
1025 assert_eq!(accounts[0].lamports(), 100);
1026 assert_eq!(accounts[1], unchanged_account);
1027
1028 let owned_account = AccountSharedData::new(1, 0, &Pubkey::default());
1030 let unchanged_account = owned_account.clone();
1031 let accounts = process_instruction(
1032 &bincode::serialize(&SystemInstruction::CreateAccount {
1033 lamports: 50,
1034 space: 2,
1035 owner: new_owner,
1036 })
1037 .unwrap(),
1038 vec![(from, from_account), (owned_key, owned_account)],
1039 vec![
1040 AccountMeta {
1041 pubkey: from,
1042 is_signer: true,
1043 is_writable: false,
1044 },
1045 AccountMeta {
1046 pubkey: owned_key,
1047 is_signer: true,
1048 is_writable: false,
1049 },
1050 ],
1051 Err(SystemError::AccountAlreadyInUse.into()),
1052 );
1053 assert_eq!(accounts[0].lamports(), 100);
1054 assert_eq!(accounts[1], unchanged_account);
1055 }
1056
1057 #[test]
1058 fn test_create_unsigned() {
1059 let new_owner = Pubkey::from([9; 32]);
1061 let from = Pubkey::new_unique();
1062 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1063 let owned_key = Pubkey::new_unique();
1064 let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1065
1066 process_instruction(
1068 &bincode::serialize(&SystemInstruction::CreateAccount {
1069 lamports: 50,
1070 space: 2,
1071 owner: new_owner,
1072 })
1073 .unwrap(),
1074 vec![
1075 (from, from_account.clone()),
1076 (owned_key, owned_account.clone()),
1077 ],
1078 vec![
1079 AccountMeta {
1080 pubkey: from,
1081 is_signer: false,
1082 is_writable: false,
1083 },
1084 AccountMeta {
1085 pubkey: owned_key,
1086 is_signer: false,
1087 is_writable: false,
1088 },
1089 ],
1090 Err(InstructionError::MissingRequiredSignature),
1091 );
1092
1093 process_instruction(
1095 &bincode::serialize(&SystemInstruction::CreateAccount {
1096 lamports: 50,
1097 space: 2,
1098 owner: new_owner,
1099 })
1100 .unwrap(),
1101 vec![(from, from_account.clone()), (owned_key, owned_account)],
1102 vec![
1103 AccountMeta {
1104 pubkey: from,
1105 is_signer: true,
1106 is_writable: false,
1107 },
1108 AccountMeta {
1109 pubkey: owned_key,
1110 is_signer: false,
1111 is_writable: false,
1112 },
1113 ],
1114 Err(InstructionError::MissingRequiredSignature),
1115 );
1116
1117 let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1119 process_instruction(
1120 &bincode::serialize(&SystemInstruction::CreateAccount {
1121 lamports: 50,
1122 space: 2,
1123 owner: new_owner,
1124 })
1125 .unwrap(),
1126 vec![(from, from_account), (owned_key, owned_account)],
1127 vec![
1128 AccountMeta {
1129 pubkey: from,
1130 is_signer: false,
1131 is_writable: false,
1132 },
1133 AccountMeta {
1134 pubkey: owned_key,
1135 is_signer: false,
1136 is_writable: false,
1137 },
1138 ],
1139 Err(InstructionError::MissingRequiredSignature),
1140 );
1141 }
1142
1143 #[test]
1144 fn test_create_sysvar_invalid_id_with_feature() {
1145 let from = Pubkey::new_unique();
1147 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1148 let to = Pubkey::new_unique();
1149 let to_account = AccountSharedData::new(0, 0, &system_program::id());
1150
1151 process_instruction(
1153 &bincode::serialize(&SystemInstruction::CreateAccount {
1154 lamports: 50,
1155 space: 2,
1156 owner: solana_sdk_ids::sysvar::id(),
1157 })
1158 .unwrap(),
1159 vec![(from, from_account), (to, to_account)],
1160 vec![
1161 AccountMeta {
1162 pubkey: from,
1163 is_signer: true,
1164 is_writable: true,
1165 },
1166 AccountMeta {
1167 pubkey: to,
1168 is_signer: true,
1169 is_writable: true,
1170 },
1171 ],
1172 Ok(()),
1173 );
1174 }
1175
1176 #[test]
1177 fn test_create_data_populated() {
1178 let new_owner = Pubkey::from([9; 32]);
1180 let from = Pubkey::new_unique();
1181 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1182 let populated_key = Pubkey::new_unique();
1183 let populated_account = AccountSharedData::from(Account {
1184 data: vec![0, 1, 2, 3],
1185 ..Account::default()
1186 });
1187
1188 process_instruction(
1189 &bincode::serialize(&SystemInstruction::CreateAccount {
1190 lamports: 50,
1191 space: 2,
1192 owner: new_owner,
1193 })
1194 .unwrap(),
1195 vec![(from, from_account), (populated_key, populated_account)],
1196 vec![
1197 AccountMeta {
1198 pubkey: from,
1199 is_signer: true,
1200 is_writable: false,
1201 },
1202 AccountMeta {
1203 pubkey: populated_key,
1204 is_signer: true,
1205 is_writable: false,
1206 },
1207 ],
1208 Err(SystemError::AccountAlreadyInUse.into()),
1209 );
1210 }
1211
1212 #[test]
1213 fn test_create_from_account_is_nonce_fail() {
1214 let nonce = Pubkey::new_unique();
1215 let nonce_account = AccountSharedData::new_data(
1216 42,
1217 &nonce::versions::Versions::new(nonce::state::State::Initialized(
1218 nonce::state::Data::default(),
1219 )),
1220 &system_program::id(),
1221 )
1222 .unwrap();
1223 let new = Pubkey::new_unique();
1224 let new_account = AccountSharedData::new(0, 0, &system_program::id());
1225
1226 process_instruction(
1227 &bincode::serialize(&SystemInstruction::CreateAccount {
1228 lamports: 42,
1229 space: 0,
1230 owner: Pubkey::new_unique(),
1231 })
1232 .unwrap(),
1233 vec![(nonce, nonce_account), (new, new_account)],
1234 vec![
1235 AccountMeta {
1236 pubkey: nonce,
1237 is_signer: true,
1238 is_writable: false,
1239 },
1240 AccountMeta {
1241 pubkey: new,
1242 is_signer: true,
1243 is_writable: true,
1244 },
1245 ],
1246 Err(InstructionError::InvalidArgument),
1247 );
1248 }
1249
1250 #[test]
1251 fn test_assign() {
1252 let new_owner = Pubkey::from([9; 32]);
1253 let pubkey = Pubkey::new_unique();
1254 let account = AccountSharedData::new(100, 0, &system_program::id());
1255
1256 process_instruction(
1258 &bincode::serialize(&SystemInstruction::Assign {
1259 owner: system_program::id(),
1260 })
1261 .unwrap(),
1262 vec![(pubkey, account.clone())],
1263 vec![AccountMeta {
1264 pubkey,
1265 is_signer: false,
1266 is_writable: true,
1267 }],
1268 Ok(()),
1269 );
1270
1271 process_instruction(
1273 &bincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1274 vec![(pubkey, account.clone())],
1275 vec![AccountMeta {
1276 pubkey,
1277 is_signer: false,
1278 is_writable: true,
1279 }],
1280 Err(InstructionError::MissingRequiredSignature),
1281 );
1282
1283 process_instruction(
1284 &bincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1285 vec![(pubkey, account.clone())],
1286 vec![AccountMeta {
1287 pubkey,
1288 is_signer: true,
1289 is_writable: true,
1290 }],
1291 Ok(()),
1292 );
1293
1294 process_instruction(
1296 &bincode::serialize(&SystemInstruction::Assign {
1297 owner: solana_sdk_ids::sysvar::id(),
1298 })
1299 .unwrap(),
1300 vec![(pubkey, account)],
1301 vec![AccountMeta {
1302 pubkey,
1303 is_signer: true,
1304 is_writable: true,
1305 }],
1306 Ok(()),
1307 );
1308 }
1309
1310 #[test]
1311 fn test_process_bogus_instruction() {
1312 let instruction = SystemInstruction::Assign {
1314 owner: Pubkey::new_unique(),
1315 };
1316 let data = serialize(&instruction).unwrap();
1317 process_instruction(
1318 &data,
1319 Vec::new(),
1320 Vec::new(),
1321 Err(InstructionError::MissingAccount),
1322 );
1323
1324 let from = Pubkey::new_unique();
1326 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1327 let instruction = SystemInstruction::Transfer { lamports: 0 };
1328 let data = serialize(&instruction).unwrap();
1329 process_instruction(
1330 &data,
1331 vec![(from, from_account)],
1332 vec![AccountMeta {
1333 pubkey: from,
1334 is_signer: true,
1335 is_writable: false,
1336 }],
1337 Err(InstructionError::MissingAccount),
1338 );
1339 }
1340
1341 #[test]
1342 fn test_transfer_lamports() {
1343 let from = Pubkey::new_unique();
1344 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1345 let to = Pubkey::from([3; 32]);
1346 let to_account = AccountSharedData::new(1, 0, &to); let transaction_accounts = vec![(from, from_account), (to, to_account)];
1348 let instruction_accounts = vec![
1349 AccountMeta {
1350 pubkey: from,
1351 is_signer: true,
1352 is_writable: true,
1353 },
1354 AccountMeta {
1355 pubkey: to,
1356 is_signer: false,
1357 is_writable: true,
1358 },
1359 ];
1360
1361 let accounts = process_instruction(
1363 &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1364 transaction_accounts.clone(),
1365 instruction_accounts.clone(),
1366 Ok(()),
1367 );
1368 assert_eq!(accounts[0].lamports(), 50);
1369 assert_eq!(accounts[1].lamports(), 51);
1370
1371 let accounts = process_instruction(
1373 &bincode::serialize(&SystemInstruction::Transfer { lamports: 101 }).unwrap(),
1374 transaction_accounts.clone(),
1375 instruction_accounts.clone(),
1376 Err(SystemError::ResultWithNegativeLamports.into()),
1377 );
1378 assert_eq!(accounts[0].lamports(), 100);
1379 assert_eq!(accounts[1].lamports(), 1);
1380
1381 let accounts = process_instruction(
1383 &bincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1384 transaction_accounts.clone(),
1385 instruction_accounts,
1386 Ok(()),
1387 );
1388 assert_eq!(accounts[0].lamports(), 100);
1389 assert_eq!(accounts[1].lamports(), 1);
1390
1391 let accounts = process_instruction(
1393 &bincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1394 transaction_accounts,
1395 vec![
1396 AccountMeta {
1397 pubkey: from,
1398 is_signer: false,
1399 is_writable: true,
1400 },
1401 AccountMeta {
1402 pubkey: to,
1403 is_signer: false,
1404 is_writable: true,
1405 },
1406 ],
1407 Err(InstructionError::MissingRequiredSignature),
1408 );
1409 assert_eq!(accounts[0].lamports(), 100);
1410 assert_eq!(accounts[1].lamports(), 1);
1411 }
1412
1413 #[test]
1414 fn test_transfer_with_seed() {
1415 let base = Pubkey::new_unique();
1416 let base_account = AccountSharedData::new(100, 0, &Pubkey::from([2; 32])); let from_seed = "42".to_string();
1418 let from_owner = system_program::id();
1419 let from = Pubkey::create_with_seed(&base, from_seed.as_str(), &from_owner).unwrap();
1420 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1421 let to = Pubkey::from([3; 32]);
1422 let to_account = AccountSharedData::new(1, 0, &to); let transaction_accounts =
1424 vec![(from, from_account), (base, base_account), (to, to_account)];
1425 let instruction_accounts = vec![
1426 AccountMeta {
1427 pubkey: from,
1428 is_signer: true,
1429 is_writable: true,
1430 },
1431 AccountMeta {
1432 pubkey: base,
1433 is_signer: true,
1434 is_writable: false,
1435 },
1436 AccountMeta {
1437 pubkey: to,
1438 is_signer: false,
1439 is_writable: true,
1440 },
1441 ];
1442
1443 let accounts = process_instruction(
1445 &bincode::serialize(&SystemInstruction::TransferWithSeed {
1446 lamports: 50,
1447 from_seed: from_seed.clone(),
1448 from_owner,
1449 })
1450 .unwrap(),
1451 transaction_accounts.clone(),
1452 instruction_accounts.clone(),
1453 Ok(()),
1454 );
1455 assert_eq!(accounts[0].lamports(), 50);
1456 assert_eq!(accounts[2].lamports(), 51);
1457
1458 let accounts = process_instruction(
1460 &bincode::serialize(&SystemInstruction::TransferWithSeed {
1461 lamports: 101,
1462 from_seed: from_seed.clone(),
1463 from_owner,
1464 })
1465 .unwrap(),
1466 transaction_accounts.clone(),
1467 instruction_accounts.clone(),
1468 Err(SystemError::ResultWithNegativeLamports.into()),
1469 );
1470 assert_eq!(accounts[0].lamports(), 100);
1471 assert_eq!(accounts[2].lamports(), 1);
1472
1473 let accounts = process_instruction(
1475 &bincode::serialize(&SystemInstruction::TransferWithSeed {
1476 lamports: 0,
1477 from_seed,
1478 from_owner,
1479 })
1480 .unwrap(),
1481 transaction_accounts,
1482 instruction_accounts,
1483 Ok(()),
1484 );
1485 assert_eq!(accounts[0].lamports(), 100);
1486 assert_eq!(accounts[2].lamports(), 1);
1487 }
1488
1489 #[test]
1490 fn test_transfer_lamports_from_nonce_account_fail() {
1491 let from = Pubkey::new_unique();
1492 let from_account = AccountSharedData::new_data(
1493 100,
1494 &nonce::versions::Versions::new(nonce::state::State::Initialized(nonce::state::Data {
1495 authority: from,
1496 ..nonce::state::Data::default()
1497 })),
1498 &system_program::id(),
1499 )
1500 .unwrap();
1501 assert_eq!(
1502 get_system_account_kind(&from_account),
1503 Some(SystemAccountKind::Nonce)
1504 );
1505 let to = Pubkey::from([3; 32]);
1506 let to_account = AccountSharedData::new(1, 0, &to); process_instruction(
1509 &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1510 vec![(from, from_account), (to, to_account)],
1511 vec![
1512 AccountMeta {
1513 pubkey: from,
1514 is_signer: true,
1515 is_writable: false,
1516 },
1517 AccountMeta {
1518 pubkey: to,
1519 is_signer: false,
1520 is_writable: false,
1521 },
1522 ],
1523 Err(InstructionError::InvalidArgument),
1524 );
1525 }
1526
1527 fn process_nonce_instruction(
1528 instruction: Instruction,
1529 expected_result: Result<(), InstructionError>,
1530 ) -> Vec<AccountSharedData> {
1531 let transaction_accounts = instruction
1532 .accounts
1533 .iter()
1534 .map(|meta| {
1535 #[allow(deprecated)]
1536 (
1537 meta.pubkey,
1538 if sysvar::recent_blockhashes::check_id(&meta.pubkey) {
1539 create_default_recent_blockhashes_account()
1540 } else if sysvar::rent::check_id(&meta.pubkey) {
1541 create_sysvar_account(&Rent::free())
1542 } else {
1543 AccountSharedData::new(0, 0, &Pubkey::new_unique())
1544 },
1545 )
1546 })
1547 .collect();
1548 process_instruction(
1549 &instruction.data,
1550 transaction_accounts,
1551 instruction.accounts,
1552 expected_result,
1553 )
1554 }
1555
1556 #[test]
1557 fn test_process_nonce_ix_no_acc_data_fail() {
1558 let none_address = Pubkey::new_unique();
1559 process_nonce_instruction(
1560 system_instruction::advance_nonce_account(&none_address, &none_address),
1561 Err(InstructionError::InvalidAccountData),
1562 );
1563 }
1564
1565 #[test]
1566 fn test_process_nonce_ix_no_keyed_accs_fail() {
1567 process_instruction(
1568 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1569 Vec::new(),
1570 Vec::new(),
1571 Err(InstructionError::MissingAccount),
1572 );
1573 }
1574
1575 #[test]
1576 fn test_process_nonce_ix_only_nonce_acc_fail() {
1577 let pubkey = Pubkey::new_unique();
1578 process_instruction(
1579 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1580 vec![(pubkey, create_default_account())],
1581 vec![AccountMeta {
1582 pubkey,
1583 is_signer: true,
1584 is_writable: true,
1585 }],
1586 Err(InstructionError::MissingAccount),
1587 );
1588 }
1589
1590 #[test]
1591 fn test_process_nonce_ix_ok() {
1592 let nonce_address = Pubkey::new_unique();
1593 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1594 #[allow(deprecated)]
1595 let blockhash_id = sysvar::recent_blockhashes::id();
1596 let accounts = process_instruction(
1597 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1598 vec![
1599 (nonce_address, nonce_account),
1600 (blockhash_id, create_default_recent_blockhashes_account()),
1601 (sysvar::rent::id(), create_default_rent_account()),
1602 ],
1603 vec![
1604 AccountMeta {
1605 pubkey: nonce_address,
1606 is_signer: true,
1607 is_writable: true,
1608 },
1609 AccountMeta {
1610 pubkey: blockhash_id,
1611 is_signer: false,
1612 is_writable: false,
1613 },
1614 AccountMeta {
1615 pubkey: sysvar::rent::id(),
1616 is_signer: false,
1617 is_writable: false,
1618 },
1619 ],
1620 Ok(()),
1621 );
1622 let blockhash = hash(&serialize(&0).unwrap());
1623 #[allow(deprecated)]
1624 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![
1625 IterItem(0u64, &blockhash, 0);
1626 sysvar::recent_blockhashes::MAX_ENTRIES
1627 ]);
1628 mock_process_instruction(
1629 &system_program::id(),
1630 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1631 vec![
1632 (nonce_address, accounts[0].clone()),
1633 (blockhash_id, new_recent_blockhashes_account),
1634 ],
1635 vec![
1636 AccountMeta {
1637 pubkey: nonce_address,
1638 is_signer: true,
1639 is_writable: true,
1640 },
1641 AccountMeta {
1642 pubkey: blockhash_id,
1643 is_signer: false,
1644 is_writable: false,
1645 },
1646 ],
1647 Ok(()),
1648 Entrypoint::register,
1649 |invoke_context: &mut InvokeContext| {
1650 invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1651 },
1652 |_invoke_context| {},
1653 );
1654 }
1655
1656 #[test]
1657 fn test_process_withdraw_ix_no_acc_data_fail() {
1658 let nonce_address = Pubkey::new_unique();
1659 process_nonce_instruction(
1660 system_instruction::withdraw_nonce_account(
1661 &nonce_address,
1662 &Pubkey::new_unique(),
1663 &nonce_address,
1664 1,
1665 ),
1666 Err(InstructionError::InvalidAccountData),
1667 );
1668 }
1669
1670 #[test]
1671 fn test_process_withdraw_ix_no_keyed_accs_fail() {
1672 process_instruction(
1673 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1674 Vec::new(),
1675 Vec::new(),
1676 Err(InstructionError::MissingAccount),
1677 );
1678 }
1679
1680 #[test]
1681 fn test_process_withdraw_ix_only_nonce_acc_fail() {
1682 let nonce_address = Pubkey::new_unique();
1683 process_instruction(
1684 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1685 vec![(nonce_address, create_default_account())],
1686 vec![AccountMeta {
1687 pubkey: nonce_address,
1688 is_signer: true,
1689 is_writable: true,
1690 }],
1691 Err(InstructionError::MissingAccount),
1692 );
1693 }
1694
1695 #[test]
1696 fn test_process_withdraw_ix_ok() {
1697 let nonce_address = Pubkey::new_unique();
1698 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1699 let pubkey = Pubkey::new_unique();
1700 #[allow(deprecated)]
1701 let blockhash_id = sysvar::recent_blockhashes::id();
1702 process_instruction(
1703 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1704 vec![
1705 (nonce_address, nonce_account),
1706 (pubkey, create_default_account()),
1707 (blockhash_id, create_default_recent_blockhashes_account()),
1708 (sysvar::rent::id(), create_default_rent_account()),
1709 ],
1710 vec![
1711 AccountMeta {
1712 pubkey: nonce_address,
1713 is_signer: true,
1714 is_writable: true,
1715 },
1716 AccountMeta {
1717 pubkey,
1718 is_signer: true,
1719 is_writable: true,
1720 },
1721 AccountMeta {
1722 pubkey: blockhash_id,
1723 is_signer: false,
1724 is_writable: false,
1725 },
1726 AccountMeta {
1727 pubkey: sysvar::rent::id(),
1728 is_signer: false,
1729 is_writable: false,
1730 },
1731 ],
1732 Ok(()),
1733 );
1734 }
1735
1736 #[test]
1737 fn test_process_initialize_ix_no_keyed_accs_fail() {
1738 process_instruction(
1739 &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(),
1740 Vec::new(),
1741 Vec::new(),
1742 Err(InstructionError::MissingAccount),
1743 );
1744 }
1745
1746 #[test]
1747 fn test_process_initialize_ix_only_nonce_acc_fail() {
1748 let nonce_address = Pubkey::new_unique();
1749 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1750 process_instruction(
1751 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1752 vec![(nonce_address, nonce_account)],
1753 vec![AccountMeta {
1754 pubkey: nonce_address,
1755 is_signer: true,
1756 is_writable: true,
1757 }],
1758 Err(InstructionError::MissingAccount),
1759 );
1760 }
1761
1762 #[test]
1763 fn test_process_initialize_ix_ok() {
1764 let nonce_address = Pubkey::new_unique();
1765 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1766 #[allow(deprecated)]
1767 let blockhash_id = sysvar::recent_blockhashes::id();
1768 process_instruction(
1769 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1770 vec![
1771 (nonce_address, nonce_account),
1772 (blockhash_id, create_default_recent_blockhashes_account()),
1773 (sysvar::rent::id(), create_default_rent_account()),
1774 ],
1775 vec![
1776 AccountMeta {
1777 pubkey: nonce_address,
1778 is_signer: true,
1779 is_writable: true,
1780 },
1781 AccountMeta {
1782 pubkey: blockhash_id,
1783 is_signer: false,
1784 is_writable: false,
1785 },
1786 AccountMeta {
1787 pubkey: sysvar::rent::id(),
1788 is_signer: false,
1789 is_writable: false,
1790 },
1791 ],
1792 Ok(()),
1793 );
1794 }
1795
1796 #[test]
1797 fn test_process_authorize_ix_ok() {
1798 let nonce_address = Pubkey::new_unique();
1799 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1800 #[allow(deprecated)]
1801 let blockhash_id = sysvar::recent_blockhashes::id();
1802 let accounts = process_instruction(
1803 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1804 vec![
1805 (nonce_address, nonce_account),
1806 (blockhash_id, create_default_recent_blockhashes_account()),
1807 (sysvar::rent::id(), create_default_rent_account()),
1808 ],
1809 vec![
1810 AccountMeta {
1811 pubkey: nonce_address,
1812 is_signer: true,
1813 is_writable: true,
1814 },
1815 AccountMeta {
1816 pubkey: blockhash_id,
1817 is_signer: false,
1818 is_writable: false,
1819 },
1820 AccountMeta {
1821 pubkey: sysvar::rent::id(),
1822 is_signer: false,
1823 is_writable: false,
1824 },
1825 ],
1826 Ok(()),
1827 );
1828 process_instruction(
1829 &serialize(&SystemInstruction::AuthorizeNonceAccount(nonce_address)).unwrap(),
1830 vec![(nonce_address, accounts[0].clone())],
1831 vec![AccountMeta {
1832 pubkey: nonce_address,
1833 is_signer: true,
1834 is_writable: true,
1835 }],
1836 Ok(()),
1837 );
1838 }
1839
1840 #[test]
1841 fn test_process_authorize_bad_account_data_fail() {
1842 let nonce_address = Pubkey::new_unique();
1843 process_nonce_instruction(
1844 system_instruction::authorize_nonce_account(
1845 &nonce_address,
1846 &Pubkey::new_unique(),
1847 &nonce_address,
1848 ),
1849 Err(InstructionError::InvalidAccountData),
1850 );
1851 }
1852
1853 #[test]
1854 fn test_nonce_initialize_with_empty_recent_blockhashes_fail() {
1855 let nonce_address = Pubkey::new_unique();
1856 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1857 #[allow(deprecated)]
1858 let blockhash_id = sysvar::recent_blockhashes::id();
1859 #[allow(deprecated)]
1860 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1861 process_instruction(
1862 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1863 vec![
1864 (nonce_address, nonce_account),
1865 (blockhash_id, new_recent_blockhashes_account),
1866 (sysvar::rent::id(), create_default_rent_account()),
1867 ],
1868 vec![
1869 AccountMeta {
1870 pubkey: nonce_address,
1871 is_signer: true,
1872 is_writable: true,
1873 },
1874 AccountMeta {
1875 pubkey: blockhash_id,
1876 is_signer: false,
1877 is_writable: false,
1878 },
1879 AccountMeta {
1880 pubkey: sysvar::rent::id(),
1881 is_signer: false,
1882 is_writable: false,
1883 },
1884 ],
1885 Err(SystemError::NonceNoRecentBlockhashes.into()),
1886 );
1887 }
1888
1889 #[test]
1890 fn test_nonce_advance_with_empty_recent_blockhashes_fail() {
1891 let nonce_address = Pubkey::new_unique();
1892 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1893 #[allow(deprecated)]
1894 let blockhash_id = sysvar::recent_blockhashes::id();
1895 let accounts = process_instruction(
1896 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1897 vec![
1898 (nonce_address, nonce_account),
1899 (blockhash_id, create_default_recent_blockhashes_account()),
1900 (sysvar::rent::id(), create_default_rent_account()),
1901 ],
1902 vec![
1903 AccountMeta {
1904 pubkey: nonce_address,
1905 is_signer: true,
1906 is_writable: true,
1907 },
1908 AccountMeta {
1909 pubkey: blockhash_id,
1910 is_signer: false,
1911 is_writable: false,
1912 },
1913 AccountMeta {
1914 pubkey: sysvar::rent::id(),
1915 is_signer: false,
1916 is_writable: false,
1917 },
1918 ],
1919 Ok(()),
1920 );
1921 #[allow(deprecated)]
1922 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1923 mock_process_instruction(
1924 &system_program::id(),
1925 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1926 vec![
1927 (nonce_address, accounts[0].clone()),
1928 (blockhash_id, new_recent_blockhashes_account),
1929 ],
1930 vec![
1931 AccountMeta {
1932 pubkey: nonce_address,
1933 is_signer: true,
1934 is_writable: true,
1935 },
1936 AccountMeta {
1937 pubkey: blockhash_id,
1938 is_signer: false,
1939 is_writable: false,
1940 },
1941 ],
1942 Err(SystemError::NonceNoRecentBlockhashes.into()),
1943 Entrypoint::register,
1944 |invoke_context: &mut InvokeContext| {
1945 invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1946 },
1947 |_invoke_context| {},
1948 );
1949 }
1950
1951 #[test]
1952 fn test_nonce_account_upgrade_check_owner() {
1953 let nonce_address = Pubkey::new_unique();
1954 let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1955 let nonce_account = AccountSharedData::new_data(
1956 1_000_000, &versions, &Pubkey::new_unique(), )
1960 .unwrap();
1961 let accounts = process_instruction(
1962 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1963 vec![(nonce_address, nonce_account.clone())],
1964 vec![AccountMeta {
1965 pubkey: nonce_address,
1966 is_signer: false,
1967 is_writable: true,
1968 }],
1969 Err(InstructionError::InvalidAccountOwner),
1970 );
1971 assert_eq!(accounts.len(), 1);
1972 assert_eq!(accounts[0], nonce_account);
1973 }
1974
1975 fn new_nonce_account(versions: NonceVersions) -> AccountSharedData {
1976 let nonce_account = AccountSharedData::new_data(
1977 1_000_000, &versions, &system_program::id(), )
1981 .unwrap();
1982 let stored: NonceVersions = nonce_account.state().unwrap();
1983 assert_eq!(stored, versions);
1984 nonce_account
1985 }
1986
1987 #[test]
1988 fn test_nonce_account_upgrade() {
1989 let nonce_address = Pubkey::new_unique();
1990 let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1991 let nonce_account = new_nonce_account(versions);
1992 let accounts = process_instruction(
1993 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1994 vec![(nonce_address, nonce_account.clone())],
1995 vec![AccountMeta {
1996 pubkey: nonce_address,
1997 is_signer: false,
1998 is_writable: true,
1999 }],
2000 Err(InstructionError::InvalidArgument),
2001 );
2002 assert_eq!(accounts.len(), 1);
2003 assert_eq!(accounts[0], nonce_account);
2004 let versions = NonceVersions::Current(Box::new(NonceState::Uninitialized));
2005 let nonce_account = new_nonce_account(versions);
2006 let accounts = process_instruction(
2007 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2008 vec![(nonce_address, nonce_account.clone())],
2009 vec![AccountMeta {
2010 pubkey: nonce_address,
2011 is_signer: false,
2012 is_writable: true,
2013 }],
2014 Err(InstructionError::InvalidArgument),
2015 );
2016 assert_eq!(accounts.len(), 1);
2017 assert_eq!(accounts[0], nonce_account);
2018 let blockhash = Hash::from([171; 32]);
2019 let durable_nonce = DurableNonce::from_blockhash(&blockhash);
2020 let data = NonceData {
2021 authority: Pubkey::new_unique(),
2022 durable_nonce,
2023 fee_calculator: FeeCalculator {
2024 lamports_per_signature: 2718,
2025 },
2026 };
2027 let versions = NonceVersions::Legacy(Box::new(NonceState::Initialized(data.clone())));
2028 let nonce_account = new_nonce_account(versions);
2029 let accounts = process_instruction(
2030 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2031 vec![(nonce_address, nonce_account.clone())],
2032 vec![AccountMeta {
2033 pubkey: nonce_address,
2034 is_signer: false,
2035 is_writable: false, }],
2037 Err(InstructionError::InvalidArgument),
2038 );
2039 assert_eq!(accounts.len(), 1);
2040 assert_eq!(accounts[0], nonce_account);
2041 let mut accounts = process_instruction(
2042 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2043 vec![(nonce_address, nonce_account)],
2044 vec![AccountMeta {
2045 pubkey: nonce_address,
2046 is_signer: false,
2047 is_writable: true,
2048 }],
2049 Ok(()),
2050 );
2051 assert_eq!(accounts.len(), 1);
2052 let nonce_account = accounts.remove(0);
2053 let durable_nonce = DurableNonce::from_blockhash(durable_nonce.as_hash());
2054 assert_ne!(data.durable_nonce, durable_nonce);
2055 let data = NonceData {
2056 durable_nonce,
2057 ..data
2058 };
2059 let upgraded_nonce_account =
2060 NonceVersions::Current(Box::new(NonceState::Initialized(data)));
2061 let stored: NonceVersions = nonce_account.state().unwrap();
2062 assert_eq!(stored, upgraded_nonce_account);
2063 let accounts = process_instruction(
2064 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2065 vec![(nonce_address, nonce_account)],
2066 vec![AccountMeta {
2067 pubkey: nonce_address,
2068 is_signer: false,
2069 is_writable: true,
2070 }],
2071 Err(InstructionError::InvalidArgument),
2072 );
2073 assert_eq!(accounts.len(), 1);
2074 let stored: NonceVersions = accounts[0].state().unwrap();
2075 assert_eq!(stored, upgraded_nonce_account);
2076 }
2077
2078 #[test]
2079 fn test_assign_native_loader_and_transfer() {
2080 for size in [0, 10] {
2081 let pubkey = Pubkey::new_unique();
2082 let account = AccountSharedData::new(100, size, &system_program::id());
2083 let accounts = process_instruction(
2084 &bincode::serialize(&SystemInstruction::Assign {
2085 owner: solana_sdk_ids::native_loader::id(),
2086 })
2087 .unwrap(),
2088 vec![(pubkey, account.clone())],
2089 vec![AccountMeta {
2090 pubkey,
2091 is_signer: true,
2092 is_writable: true,
2093 }],
2094 Ok(()),
2095 );
2096 assert_eq!(accounts[0].owner(), &solana_sdk_ids::native_loader::id());
2097 assert_eq!(accounts[0].lamports(), 100);
2098
2099 let pubkey2 = Pubkey::new_unique();
2100 let accounts = process_instruction(
2101 &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
2102 vec![
2103 (
2104 pubkey2,
2105 AccountSharedData::new(100, 0, &system_program::id()),
2106 ),
2107 (pubkey, accounts[0].clone()),
2108 ],
2109 vec![
2110 AccountMeta {
2111 pubkey: pubkey2,
2112 is_signer: true,
2113 is_writable: true,
2114 },
2115 AccountMeta {
2116 pubkey,
2117 is_signer: false,
2118 is_writable: true,
2119 },
2120 ],
2121 Ok(()),
2122 );
2123 assert_eq!(accounts[1].owner(), &solana_sdk_ids::native_loader::id());
2124 assert_eq!(accounts[1].lamports(), 150);
2125 }
2126 }
2127
2128 #[test]
2129 fn test_create_account_allow_prefund() {
2130 let new_owner = Pubkey::from([9; 32]);
2131 let to = Pubkey::new_unique();
2132 let from = Pubkey::new_unique();
2133 let ix_accounts = vec![AccountMeta::new(to, true), AccountMeta::new(from, true)];
2134
2135 let accounts = process_instruction(
2137 &bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2138 lamports: 50,
2139 space: 2,
2140 owner: new_owner,
2141 })
2142 .unwrap(),
2143 vec![
2144 (to, AccountSharedData::new(100, 0, &Pubkey::default())),
2145 (from, AccountSharedData::new(100, 0, &system_program::id())),
2146 ],
2147 ix_accounts,
2148 Ok(()),
2149 );
2150 assert_eq!(accounts[0].lamports(), 150);
2151 assert_eq!(accounts[0].owner(), &new_owner);
2152 assert_eq!(accounts[0].data(), &[0, 0]);
2153 assert_eq!(accounts[1].lamports(), 50);
2154
2155 let accounts = process_instruction(
2157 &bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2158 lamports: 0,
2159 space: 2,
2160 owner: new_owner,
2161 })
2162 .unwrap(),
2163 vec![(to, AccountSharedData::new(100, 0, &Pubkey::default()))],
2164 vec![AccountMeta::new(to, true)],
2165 Ok(()),
2166 );
2167 assert_eq!(accounts[0].lamports(), 100);
2168 assert_eq!(accounts[0].owner(), &new_owner);
2169 assert_eq!(accounts[0].data(), &[0, 0]);
2170
2171 use solana_program_runtime::invoke_context::mock_process_instruction_with_feature_set;
2173 mock_process_instruction_with_feature_set(
2174 &system_program::id(),
2175 &bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2176 lamports: 50,
2177 space: 0,
2178 owner: new_owner,
2179 })
2180 .unwrap(),
2181 vec![
2182 (to, AccountSharedData::new(0, 0, &Pubkey::default())),
2183 (from, AccountSharedData::new(100, 0, &system_program::id())),
2184 ],
2185 vec![AccountMeta::new(to, true), AccountMeta::new(from, true)],
2186 Err(InstructionError::InvalidInstructionData),
2187 Entrypoint::register,
2188 |_| {},
2189 |_| {},
2190 &solana_svm_feature_set::SVMFeatureSet::default(),
2191 );
2192 }
2193
2194 #[test]
2195 fn test_create_account_allow_prefund_already_in_use() {
2196 let new_owner = Pubkey::from([9; 32]);
2197 let to = Pubkey::new_unique();
2198 let from = Pubkey::new_unique();
2199 let from_account = AccountSharedData::new(100, 0, &system_program::id());
2200 let ix_data = bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2201 lamports: 50,
2202 space: 2,
2203 owner: new_owner,
2204 })
2205 .unwrap();
2206 let ix_accounts = vec![AccountMeta::new(to, true), AccountMeta::new(from, true)];
2207
2208 process_instruction(
2210 &ix_data,
2211 vec![
2212 (to, AccountSharedData::new(0, 1, &Pubkey::default())),
2213 (from, from_account.clone()),
2214 ],
2215 ix_accounts.clone(),
2216 Err(SystemError::AccountAlreadyInUse.into()),
2217 );
2218
2219 process_instruction(
2221 &ix_data,
2222 vec![
2223 (to, AccountSharedData::new(0, 0, &Pubkey::from([5; 32]))),
2224 (from, from_account),
2225 ],
2226 ix_accounts,
2227 Err(SystemError::AccountAlreadyInUse.into()),
2228 );
2229 }
2230
2231 #[test]
2232 fn test_create_account_allow_prefund_missing_signer() {
2233 let new_owner = Pubkey::from([9; 32]);
2234 let to = Pubkey::new_unique();
2235 let from = Pubkey::new_unique();
2236 let tx_accounts = vec![
2237 (to, AccountSharedData::new(0, 0, &Pubkey::default())),
2238 (from, AccountSharedData::new(100, 0, &system_program::id())),
2239 ];
2240 let ix_data = bincode::serialize(&SystemInstruction::CreateAccountAllowPrefund {
2241 lamports: 50,
2242 space: 2,
2243 owner: new_owner,
2244 })
2245 .unwrap();
2246
2247 process_instruction(
2249 &ix_data,
2250 tx_accounts.clone(),
2251 vec![AccountMeta::new(to, true), AccountMeta::new(from, false)],
2252 Err(InstructionError::MissingRequiredSignature),
2253 );
2254
2255 process_instruction(
2257 &ix_data,
2258 tx_accounts,
2259 vec![AccountMeta::new(to, false), AccountMeta::new(from, true)],
2260 Err(InstructionError::MissingRequiredSignature),
2261 );
2262 }
2263}