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