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_log_collector::ic_msg,
10 solana_nonce as nonce,
11 solana_program_runtime::{
12 declare_process_instruction, invoke_context::InvokeContext,
13 sysvar_cache::get_sysvar_with_account_check,
14 },
15 solana_pubkey::Pubkey,
16 solana_sdk_ids::system_program,
17 solana_system_interface::{
18 error::SystemError, instruction::SystemInstruction, MAX_PERMITTED_DATA_LENGTH,
19 },
20 solana_transaction_context::{
21 BorrowedAccount, IndexOfAccount, InstructionContext, TransactionContext,
22 },
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 =
306 limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)?;
307
308 trace!("process_instruction: {:?}", instruction);
309
310 let signers = instruction_context.get_signers(transaction_context)?;
311 match instruction {
312 SystemInstruction::CreateAccount {
313 lamports,
314 space,
315 owner,
316 } => {
317 instruction_context.check_number_of_instruction_accounts(2)?;
318 let to_address = Address::create(
319 transaction_context.get_key_of_account_at_index(
320 instruction_context.get_index_of_instruction_account_in_transaction(1)?,
321 )?,
322 None,
323 invoke_context,
324 )?;
325 create_account(
326 0,
327 1,
328 &to_address,
329 lamports,
330 space,
331 &owner,
332 &signers,
333 invoke_context,
334 transaction_context,
335 instruction_context,
336 )
337 }
338 SystemInstruction::CreateAccountWithSeed {
339 base,
340 seed,
341 lamports,
342 space,
343 owner,
344 } => {
345 instruction_context.check_number_of_instruction_accounts(2)?;
346 let to_address = Address::create(
347 transaction_context.get_key_of_account_at_index(
348 instruction_context.get_index_of_instruction_account_in_transaction(1)?,
349 )?,
350 Some((&base, &seed, &owner)),
351 invoke_context,
352 )?;
353 create_account(
354 0,
355 1,
356 &to_address,
357 lamports,
358 space,
359 &owner,
360 &signers,
361 invoke_context,
362 transaction_context,
363 instruction_context,
364 )
365 }
366 SystemInstruction::Assign { owner } => {
367 instruction_context.check_number_of_instruction_accounts(1)?;
368 let mut account =
369 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
370 let address = Address::create(
371 transaction_context.get_key_of_account_at_index(
372 instruction_context.get_index_of_instruction_account_in_transaction(0)?,
373 )?,
374 None,
375 invoke_context,
376 )?;
377 assign(&mut account, &address, &owner, &signers, invoke_context)
378 }
379 SystemInstruction::Transfer { lamports } => {
380 instruction_context.check_number_of_instruction_accounts(2)?;
381 transfer(
382 0,
383 1,
384 lamports,
385 invoke_context,
386 transaction_context,
387 instruction_context,
388 )
389 }
390 SystemInstruction::TransferWithSeed {
391 lamports,
392 from_seed,
393 from_owner,
394 } => {
395 instruction_context.check_number_of_instruction_accounts(3)?;
396 transfer_with_seed(
397 0,
398 1,
399 &from_seed,
400 &from_owner,
401 2,
402 lamports,
403 invoke_context,
404 transaction_context,
405 instruction_context,
406 )
407 }
408 SystemInstruction::AdvanceNonceAccount => {
409 instruction_context.check_number_of_instruction_accounts(1)?;
410 let mut me =
411 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
412 #[allow(deprecated)]
413 let recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
414 invoke_context,
415 instruction_context,
416 1,
417 )?;
418 if recent_blockhashes.is_empty() {
419 ic_msg!(
420 invoke_context,
421 "Advance nonce account: recent blockhash list is empty",
422 );
423 return Err(SystemError::NonceNoRecentBlockhashes.into());
424 }
425 advance_nonce_account(&mut me, &signers, invoke_context)
426 }
427 SystemInstruction::WithdrawNonceAccount(lamports) => {
428 instruction_context.check_number_of_instruction_accounts(2)?;
429 #[allow(deprecated)]
430 let _recent_blockhashes = get_sysvar_with_account_check::recent_blockhashes(
431 invoke_context,
432 instruction_context,
433 2,
434 )?;
435 let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 3)?;
436 withdraw_nonce_account(
437 0,
438 lamports,
439 1,
440 &rent,
441 &signers,
442 invoke_context,
443 transaction_context,
444 instruction_context,
445 )
446 }
447 SystemInstruction::InitializeNonceAccount(authorized) => {
448 instruction_context.check_number_of_instruction_accounts(1)?;
449 let mut me =
450 instruction_context.try_borrow_instruction_account(transaction_context, 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 = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 2)?;
465 initialize_nonce_account(&mut me, &authorized, &rent, invoke_context)
466 }
467 SystemInstruction::AuthorizeNonceAccount(nonce_authority) => {
468 instruction_context.check_number_of_instruction_accounts(1)?;
469 let mut me =
470 instruction_context.try_borrow_instruction_account(transaction_context, 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 =
476 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
477 if !system_program::check_id(nonce_account.get_owner()) {
478 return Err(InstructionError::InvalidAccountOwner);
479 }
480 if !nonce_account.is_writable() {
481 return Err(InstructionError::InvalidArgument);
482 }
483 let nonce_versions: nonce::versions::Versions = nonce_account.get_state()?;
484 match nonce_versions.upgrade() {
485 None => Err(InstructionError::InvalidArgument),
486 Some(nonce_versions) => nonce_account.set_state(&nonce_versions),
487 }
488 }
489 SystemInstruction::Allocate { space } => {
490 instruction_context.check_number_of_instruction_accounts(1)?;
491 let mut account =
492 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
493 let address = Address::create(
494 transaction_context.get_key_of_account_at_index(
495 instruction_context.get_index_of_instruction_account_in_transaction(0)?,
496 )?,
497 None,
498 invoke_context,
499 )?;
500 allocate(&mut account, &address, space, &signers, invoke_context)
501 }
502 SystemInstruction::AllocateWithSeed {
503 base,
504 seed,
505 space,
506 owner,
507 } => {
508 instruction_context.check_number_of_instruction_accounts(1)?;
509 let mut account =
510 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
511 let address = Address::create(
512 transaction_context.get_key_of_account_at_index(
513 instruction_context.get_index_of_instruction_account_in_transaction(0)?,
514 )?,
515 Some((&base, &seed, &owner)),
516 invoke_context,
517 )?;
518 allocate_and_assign(
519 &mut account,
520 &address,
521 space,
522 &owner,
523 &signers,
524 invoke_context,
525 )
526 }
527 SystemInstruction::AssignWithSeed { base, seed, owner } => {
528 instruction_context.check_number_of_instruction_accounts(1)?;
529 let mut account =
530 instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
531 let address = Address::create(
532 transaction_context.get_key_of_account_at_index(
533 instruction_context.get_index_of_instruction_account_in_transaction(0)?,
534 )?,
535 Some((&base, &seed, &owner)),
536 invoke_context,
537 )?;
538 assign(&mut account, &address, &owner, &signers, invoke_context)
539 }
540 }
541});
542
543#[cfg(test)]
544mod tests {
545 #[allow(deprecated)]
546 use solana_sdk::{
547 account::{
548 self, create_account_shared_data_with_fields, to_account, Account, AccountSharedData,
549 ReadableAccount, DUMMY_INHERITABLE_ACCOUNT_FIELDS,
550 },
551 fee_calculator::FeeCalculator,
552 hash::{hash, Hash},
553 instruction::{AccountMeta, Instruction, InstructionError},
554 nonce::{
555 self,
556 state::{
557 Data as NonceData, DurableNonce, State as NonceState, Versions as NonceVersions,
558 },
559 },
560 nonce_account, system_instruction, system_program,
561 sysvar::{
562 self,
563 recent_blockhashes::{IntoIterSorted, IterItem, RecentBlockhashes, MAX_ENTRIES},
564 rent::Rent,
565 },
566 };
567 use {
568 super::*,
569 bincode::serialize,
570 solana_nonce_account::{get_system_account_kind, SystemAccountKind},
571 solana_program_runtime::{
572 invoke_context::mock_process_instruction, with_mock_invoke_context,
573 },
574 std::collections::BinaryHeap,
575 };
576
577 impl From<Pubkey> for Address {
578 fn from(address: Pubkey) -> Self {
579 Self {
580 address,
581 base: None,
582 }
583 }
584 }
585
586 fn process_instruction(
587 instruction_data: &[u8],
588 transaction_accounts: Vec<(Pubkey, AccountSharedData)>,
589 instruction_accounts: Vec<AccountMeta>,
590 expected_result: Result<(), InstructionError>,
591 ) -> Vec<AccountSharedData> {
592 mock_process_instruction(
593 &system_program::id(),
594 Vec::new(),
595 instruction_data,
596 transaction_accounts,
597 instruction_accounts,
598 expected_result,
599 Entrypoint::vm,
600 |_invoke_context| {},
601 |_invoke_context| {},
602 )
603 }
604
605 fn create_default_account() -> AccountSharedData {
606 AccountSharedData::new(0, 0, &Pubkey::new_unique())
607 }
608 #[allow(deprecated)]
609 fn create_recent_blockhashes_account_for_test<'a, I>(
610 recent_blockhash_iter: I,
611 ) -> AccountSharedData
612 where
613 I: IntoIterator<Item = IterItem<'a>>,
614 {
615 let mut account = create_account_shared_data_with_fields::<RecentBlockhashes>(
616 &RecentBlockhashes::default(),
617 DUMMY_INHERITABLE_ACCOUNT_FIELDS,
618 );
619 let sorted = BinaryHeap::from_iter(recent_blockhash_iter);
620 let sorted_iter = IntoIterSorted::new(sorted);
621 let recent_blockhash_iter = sorted_iter.take(MAX_ENTRIES);
622 let recent_blockhashes: RecentBlockhashes = recent_blockhash_iter.collect();
623 to_account(&recent_blockhashes, &mut account);
624 account
625 }
626 fn create_default_recent_blockhashes_account() -> AccountSharedData {
627 #[allow(deprecated)]
628 create_recent_blockhashes_account_for_test(vec![
629 IterItem(0u64, &Hash::default(), 0);
630 sysvar::recent_blockhashes::MAX_ENTRIES
631 ])
632 }
633 fn create_default_rent_account() -> AccountSharedData {
634 account::create_account_shared_data_for_test(&Rent::free())
635 }
636
637 #[test]
638 fn test_create_account() {
639 let new_owner = Pubkey::from([9; 32]);
640 let from = Pubkey::new_unique();
641 let to = Pubkey::new_unique();
642 let from_account = AccountSharedData::new(100, 0, &system_program::id());
643 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
644
645 let accounts = process_instruction(
646 &bincode::serialize(&SystemInstruction::CreateAccount {
647 lamports: 50,
648 space: 2,
649 owner: new_owner,
650 })
651 .unwrap(),
652 vec![(from, from_account), (to, to_account)],
653 vec![
654 AccountMeta {
655 pubkey: from,
656 is_signer: true,
657 is_writable: true,
658 },
659 AccountMeta {
660 pubkey: to,
661 is_signer: true,
662 is_writable: true,
663 },
664 ],
665 Ok(()),
666 );
667 assert_eq!(accounts[0].lamports(), 50);
668 assert_eq!(accounts[1].lamports(), 50);
669 assert_eq!(accounts[1].owner(), &new_owner);
670 assert_eq!(accounts[1].data(), &[0, 0]);
671 }
672
673 #[test]
674 fn test_create_account_with_seed() {
675 let new_owner = Pubkey::from([9; 32]);
676 let from = Pubkey::new_unique();
677 let seed = "shiny pepper";
678 let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
679 let from_account = AccountSharedData::new(100, 0, &system_program::id());
680 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
681
682 let accounts = process_instruction(
683 &bincode::serialize(&SystemInstruction::CreateAccountWithSeed {
684 base: from,
685 seed: seed.to_string(),
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_separate_base_account() {
714 let new_owner = Pubkey::from([9; 32]);
715 let from = Pubkey::new_unique();
716 let base = Pubkey::new_unique();
717 let seed = "shiny pepper";
718 let to = Pubkey::create_with_seed(&base, seed, &new_owner).unwrap();
719 let from_account = AccountSharedData::new(100, 0, &system_program::id());
720 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
721 let base_account = AccountSharedData::new(0, 0, &Pubkey::default());
722
723 let accounts = process_instruction(
724 &bincode::serialize(&SystemInstruction::CreateAccountWithSeed {
725 base,
726 seed: seed.to_string(),
727 lamports: 50,
728 space: 2,
729 owner: new_owner,
730 })
731 .unwrap(),
732 vec![(from, from_account), (to, to_account), (base, base_account)],
733 vec![
734 AccountMeta {
735 pubkey: from,
736 is_signer: true,
737 is_writable: true,
738 },
739 AccountMeta {
740 pubkey: to,
741 is_signer: false,
742 is_writable: true,
743 },
744 AccountMeta {
745 pubkey: base,
746 is_signer: true,
747 is_writable: false,
748 },
749 ],
750 Ok(()),
751 );
752 assert_eq!(accounts[0].lamports(), 50);
753 assert_eq!(accounts[1].lamports(), 50);
754 assert_eq!(accounts[1].owner(), &new_owner);
755 assert_eq!(accounts[1].data(), &[0, 0]);
756 }
757
758 #[test]
759 fn test_address_create_with_seed_mismatch() {
760 with_mock_invoke_context!(invoke_context, transaction_context, Vec::new());
761 let from = Pubkey::new_unique();
762 let seed = "dull boy";
763 let to = Pubkey::new_unique();
764 let owner = Pubkey::new_unique();
765
766 assert_eq!(
767 Address::create(&to, Some((&from, seed, &owner)), &invoke_context),
768 Err(SystemError::AddressWithSeedMismatch.into())
769 );
770 }
771
772 #[test]
773 fn test_create_account_with_seed_missing_sig() {
774 let new_owner = Pubkey::from([9; 32]);
775 let from = Pubkey::new_unique();
776 let seed = "dull boy";
777 let to = Pubkey::create_with_seed(&from, seed, &new_owner).unwrap();
778 let from_account = AccountSharedData::new(100, 0, &system_program::id());
779 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
780
781 let accounts = process_instruction(
782 &bincode::serialize(&SystemInstruction::CreateAccount {
783 lamports: 50,
784 space: 2,
785 owner: new_owner,
786 })
787 .unwrap(),
788 vec![(from, from_account), (to, to_account)],
789 vec![
790 AccountMeta {
791 pubkey: from,
792 is_signer: true,
793 is_writable: false,
794 },
795 AccountMeta {
796 pubkey: to,
797 is_signer: false,
798 is_writable: false,
799 },
800 ],
801 Err(InstructionError::MissingRequiredSignature),
802 );
803 assert_eq!(accounts[0].lamports(), 100);
804 assert_eq!(accounts[1], AccountSharedData::default());
805 }
806
807 #[test]
808 fn test_create_with_zero_lamports() {
809 let new_owner = Pubkey::from([9; 32]);
811 let from = Pubkey::new_unique();
812 let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique()); let to = Pubkey::new_unique();
814 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
815
816 let accounts = process_instruction(
817 &bincode::serialize(&SystemInstruction::CreateAccount {
818 lamports: 0,
819 space: 2,
820 owner: new_owner,
821 })
822 .unwrap(),
823 vec![(from, from_account), (to, to_account)],
824 vec![
825 AccountMeta {
826 pubkey: from,
827 is_signer: true,
828 is_writable: true,
829 },
830 AccountMeta {
831 pubkey: to,
832 is_signer: true,
833 is_writable: true,
834 },
835 ],
836 Ok(()),
837 );
838 assert_eq!(accounts[0].lamports(), 100);
839 assert_eq!(accounts[1].lamports(), 0);
840 assert_eq!(*accounts[1].owner(), new_owner);
841 assert_eq!(accounts[1].data(), &[0, 0]);
842 }
843
844 #[test]
845 fn test_create_negative_lamports() {
846 let new_owner = Pubkey::from([9; 32]);
848 let from = Pubkey::new_unique();
849 let from_account = AccountSharedData::new(100, 0, &Pubkey::new_unique());
850 let to = Pubkey::new_unique();
851 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
852
853 process_instruction(
854 &bincode::serialize(&SystemInstruction::CreateAccount {
855 lamports: 150,
856 space: 2,
857 owner: new_owner,
858 })
859 .unwrap(),
860 vec![(from, from_account), (to, to_account)],
861 vec![
862 AccountMeta {
863 pubkey: from,
864 is_signer: true,
865 is_writable: true,
866 },
867 AccountMeta {
868 pubkey: to,
869 is_signer: true,
870 is_writable: true,
871 },
872 ],
873 Err(SystemError::ResultWithNegativeLamports.into()),
874 );
875 }
876
877 #[test]
878 fn test_request_more_than_allowed_data_length() {
879 let from = Pubkey::new_unique();
880 let from_account = AccountSharedData::new(100, 0, &system_program::id());
881 let to = Pubkey::new_unique();
882 let to_account = AccountSharedData::new(0, 0, &Pubkey::default());
883 let instruction_accounts = vec![
884 AccountMeta {
885 pubkey: from,
886 is_signer: true,
887 is_writable: true,
888 },
889 AccountMeta {
890 pubkey: to,
891 is_signer: true,
892 is_writable: true,
893 },
894 ];
895
896 process_instruction(
898 &bincode::serialize(&SystemInstruction::CreateAccount {
899 lamports: 50,
900 space: MAX_PERMITTED_DATA_LENGTH + 1,
901 owner: system_program::id(),
902 })
903 .unwrap(),
904 vec![(from, from_account.clone()), (to, to_account.clone())],
905 instruction_accounts.clone(),
906 Err(SystemError::InvalidAccountDataLength.into()),
907 );
908
909 let accounts = process_instruction(
911 &bincode::serialize(&SystemInstruction::CreateAccount {
912 lamports: 50,
913 space: MAX_PERMITTED_DATA_LENGTH,
914 owner: system_program::id(),
915 })
916 .unwrap(),
917 vec![(from, from_account), (to, to_account)],
918 instruction_accounts,
919 Ok(()),
920 );
921 assert_eq!(accounts[1].lamports(), 50);
922 assert_eq!(accounts[1].data().len() as u64, MAX_PERMITTED_DATA_LENGTH);
923 }
924
925 #[test]
926 fn test_create_already_in_use() {
927 let new_owner = Pubkey::from([9; 32]);
928 let from = Pubkey::new_unique();
929 let from_account = AccountSharedData::new(100, 0, &system_program::id());
930 let owned_key = Pubkey::new_unique();
931
932 let original_program_owner = Pubkey::from([5; 32]);
934 let owned_account = AccountSharedData::new(0, 0, &original_program_owner);
935 let unchanged_account = owned_account.clone();
936 let accounts = process_instruction(
937 &bincode::serialize(&SystemInstruction::CreateAccount {
938 lamports: 50,
939 space: 2,
940 owner: new_owner,
941 })
942 .unwrap(),
943 vec![(from, from_account.clone()), (owned_key, owned_account)],
944 vec![
945 AccountMeta {
946 pubkey: from,
947 is_signer: true,
948 is_writable: false,
949 },
950 AccountMeta {
951 pubkey: owned_key,
952 is_signer: true,
953 is_writable: false,
954 },
955 ],
956 Err(SystemError::AccountAlreadyInUse.into()),
957 );
958 assert_eq!(accounts[0].lamports(), 100);
959 assert_eq!(accounts[1], unchanged_account);
960
961 let owned_account = AccountSharedData::new(0, 1, &Pubkey::default());
963 let unchanged_account = owned_account.clone();
964 let accounts = process_instruction(
965 &bincode::serialize(&SystemInstruction::CreateAccount {
966 lamports: 50,
967 space: 2,
968 owner: new_owner,
969 })
970 .unwrap(),
971 vec![(from, from_account.clone()), (owned_key, owned_account)],
972 vec![
973 AccountMeta {
974 pubkey: from,
975 is_signer: true,
976 is_writable: false,
977 },
978 AccountMeta {
979 pubkey: owned_key,
980 is_signer: true,
981 is_writable: false,
982 },
983 ],
984 Err(SystemError::AccountAlreadyInUse.into()),
985 );
986 assert_eq!(accounts[0].lamports(), 100);
987 assert_eq!(accounts[1], unchanged_account);
988
989 let owned_account = AccountSharedData::new(1, 0, &Pubkey::default());
991 let unchanged_account = owned_account.clone();
992 let accounts = process_instruction(
993 &bincode::serialize(&SystemInstruction::CreateAccount {
994 lamports: 50,
995 space: 2,
996 owner: new_owner,
997 })
998 .unwrap(),
999 vec![(from, from_account), (owned_key, owned_account)],
1000 vec![
1001 AccountMeta {
1002 pubkey: from,
1003 is_signer: true,
1004 is_writable: false,
1005 },
1006 AccountMeta {
1007 pubkey: owned_key,
1008 is_signer: true,
1009 is_writable: false,
1010 },
1011 ],
1012 Err(SystemError::AccountAlreadyInUse.into()),
1013 );
1014 assert_eq!(accounts[0].lamports(), 100);
1015 assert_eq!(accounts[1], unchanged_account);
1016 }
1017
1018 #[test]
1019 fn test_create_unsigned() {
1020 let new_owner = Pubkey::from([9; 32]);
1022 let from = Pubkey::new_unique();
1023 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1024 let owned_key = Pubkey::new_unique();
1025 let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1026
1027 process_instruction(
1029 &bincode::serialize(&SystemInstruction::CreateAccount {
1030 lamports: 50,
1031 space: 2,
1032 owner: new_owner,
1033 })
1034 .unwrap(),
1035 vec![
1036 (from, from_account.clone()),
1037 (owned_key, owned_account.clone()),
1038 ],
1039 vec![
1040 AccountMeta {
1041 pubkey: from,
1042 is_signer: false,
1043 is_writable: false,
1044 },
1045 AccountMeta {
1046 pubkey: owned_key,
1047 is_signer: false,
1048 is_writable: false,
1049 },
1050 ],
1051 Err(InstructionError::MissingRequiredSignature),
1052 );
1053
1054 process_instruction(
1056 &bincode::serialize(&SystemInstruction::CreateAccount {
1057 lamports: 50,
1058 space: 2,
1059 owner: new_owner,
1060 })
1061 .unwrap(),
1062 vec![(from, from_account.clone()), (owned_key, owned_account)],
1063 vec![
1064 AccountMeta {
1065 pubkey: from,
1066 is_signer: true,
1067 is_writable: false,
1068 },
1069 AccountMeta {
1070 pubkey: owned_key,
1071 is_signer: false,
1072 is_writable: false,
1073 },
1074 ],
1075 Err(InstructionError::MissingRequiredSignature),
1076 );
1077
1078 let owned_account = AccountSharedData::new(0, 0, &Pubkey::default());
1080 process_instruction(
1081 &bincode::serialize(&SystemInstruction::CreateAccount {
1082 lamports: 50,
1083 space: 2,
1084 owner: new_owner,
1085 })
1086 .unwrap(),
1087 vec![(from, from_account), (owned_key, owned_account)],
1088 vec![
1089 AccountMeta {
1090 pubkey: from,
1091 is_signer: false,
1092 is_writable: false,
1093 },
1094 AccountMeta {
1095 pubkey: owned_key,
1096 is_signer: false,
1097 is_writable: false,
1098 },
1099 ],
1100 Err(InstructionError::MissingRequiredSignature),
1101 );
1102 }
1103
1104 #[test]
1105 fn test_create_sysvar_invalid_id_with_feature() {
1106 let from = Pubkey::new_unique();
1108 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1109 let to = Pubkey::new_unique();
1110 let to_account = AccountSharedData::new(0, 0, &system_program::id());
1111
1112 process_instruction(
1114 &bincode::serialize(&SystemInstruction::CreateAccount {
1115 lamports: 50,
1116 space: 2,
1117 owner: sysvar::id(),
1118 })
1119 .unwrap(),
1120 vec![(from, from_account), (to, to_account)],
1121 vec![
1122 AccountMeta {
1123 pubkey: from,
1124 is_signer: true,
1125 is_writable: true,
1126 },
1127 AccountMeta {
1128 pubkey: to,
1129 is_signer: true,
1130 is_writable: true,
1131 },
1132 ],
1133 Ok(()),
1134 );
1135 }
1136
1137 #[test]
1138 fn test_create_data_populated() {
1139 let new_owner = Pubkey::from([9; 32]);
1141 let from = Pubkey::new_unique();
1142 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1143 let populated_key = Pubkey::new_unique();
1144 let populated_account = AccountSharedData::from(Account {
1145 data: vec![0, 1, 2, 3],
1146 ..Account::default()
1147 });
1148
1149 process_instruction(
1150 &bincode::serialize(&SystemInstruction::CreateAccount {
1151 lamports: 50,
1152 space: 2,
1153 owner: new_owner,
1154 })
1155 .unwrap(),
1156 vec![(from, from_account), (populated_key, populated_account)],
1157 vec![
1158 AccountMeta {
1159 pubkey: from,
1160 is_signer: true,
1161 is_writable: false,
1162 },
1163 AccountMeta {
1164 pubkey: populated_key,
1165 is_signer: true,
1166 is_writable: false,
1167 },
1168 ],
1169 Err(SystemError::AccountAlreadyInUse.into()),
1170 );
1171 }
1172
1173 #[test]
1174 fn test_create_from_account_is_nonce_fail() {
1175 let nonce = Pubkey::new_unique();
1176 let nonce_account = AccountSharedData::new_data(
1177 42,
1178 &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::default())),
1179 &system_program::id(),
1180 )
1181 .unwrap();
1182 let new = Pubkey::new_unique();
1183 let new_account = AccountSharedData::new(0, 0, &system_program::id());
1184
1185 process_instruction(
1186 &bincode::serialize(&SystemInstruction::CreateAccount {
1187 lamports: 42,
1188 space: 0,
1189 owner: Pubkey::new_unique(),
1190 })
1191 .unwrap(),
1192 vec![(nonce, nonce_account), (new, new_account)],
1193 vec![
1194 AccountMeta {
1195 pubkey: nonce,
1196 is_signer: true,
1197 is_writable: false,
1198 },
1199 AccountMeta {
1200 pubkey: new,
1201 is_signer: true,
1202 is_writable: true,
1203 },
1204 ],
1205 Err(InstructionError::InvalidArgument),
1206 );
1207 }
1208
1209 #[test]
1210 fn test_assign() {
1211 let new_owner = Pubkey::from([9; 32]);
1212 let pubkey = Pubkey::new_unique();
1213 let account = AccountSharedData::new(100, 0, &system_program::id());
1214
1215 process_instruction(
1217 &bincode::serialize(&SystemInstruction::Assign {
1218 owner: system_program::id(),
1219 })
1220 .unwrap(),
1221 vec![(pubkey, account.clone())],
1222 vec![AccountMeta {
1223 pubkey,
1224 is_signer: false,
1225 is_writable: true,
1226 }],
1227 Ok(()),
1228 );
1229
1230 process_instruction(
1232 &bincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1233 vec![(pubkey, account.clone())],
1234 vec![AccountMeta {
1235 pubkey,
1236 is_signer: false,
1237 is_writable: true,
1238 }],
1239 Err(InstructionError::MissingRequiredSignature),
1240 );
1241
1242 process_instruction(
1243 &bincode::serialize(&SystemInstruction::Assign { owner: new_owner }).unwrap(),
1244 vec![(pubkey, account.clone())],
1245 vec![AccountMeta {
1246 pubkey,
1247 is_signer: true,
1248 is_writable: true,
1249 }],
1250 Ok(()),
1251 );
1252
1253 process_instruction(
1255 &bincode::serialize(&SystemInstruction::Assign {
1256 owner: sysvar::id(),
1257 })
1258 .unwrap(),
1259 vec![(pubkey, account)],
1260 vec![AccountMeta {
1261 pubkey,
1262 is_signer: true,
1263 is_writable: true,
1264 }],
1265 Ok(()),
1266 );
1267 }
1268
1269 #[test]
1270 fn test_process_bogus_instruction() {
1271 let instruction = SystemInstruction::Assign {
1273 owner: Pubkey::new_unique(),
1274 };
1275 let data = serialize(&instruction).unwrap();
1276 process_instruction(
1277 &data,
1278 Vec::new(),
1279 Vec::new(),
1280 Err(InstructionError::NotEnoughAccountKeys),
1281 );
1282
1283 let from = Pubkey::new_unique();
1285 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1286 let instruction = SystemInstruction::Transfer { lamports: 0 };
1287 let data = serialize(&instruction).unwrap();
1288 process_instruction(
1289 &data,
1290 vec![(from, from_account)],
1291 vec![AccountMeta {
1292 pubkey: from,
1293 is_signer: true,
1294 is_writable: false,
1295 }],
1296 Err(InstructionError::NotEnoughAccountKeys),
1297 );
1298 }
1299
1300 #[test]
1301 fn test_transfer_lamports() {
1302 let from = Pubkey::new_unique();
1303 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1304 let to = Pubkey::from([3; 32]);
1305 let to_account = AccountSharedData::new(1, 0, &to); let transaction_accounts = vec![(from, from_account), (to, to_account)];
1307 let instruction_accounts = vec![
1308 AccountMeta {
1309 pubkey: from,
1310 is_signer: true,
1311 is_writable: true,
1312 },
1313 AccountMeta {
1314 pubkey: to,
1315 is_signer: false,
1316 is_writable: true,
1317 },
1318 ];
1319
1320 let accounts = process_instruction(
1322 &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1323 transaction_accounts.clone(),
1324 instruction_accounts.clone(),
1325 Ok(()),
1326 );
1327 assert_eq!(accounts[0].lamports(), 50);
1328 assert_eq!(accounts[1].lamports(), 51);
1329
1330 let accounts = process_instruction(
1332 &bincode::serialize(&SystemInstruction::Transfer { lamports: 101 }).unwrap(),
1333 transaction_accounts.clone(),
1334 instruction_accounts.clone(),
1335 Err(SystemError::ResultWithNegativeLamports.into()),
1336 );
1337 assert_eq!(accounts[0].lamports(), 100);
1338 assert_eq!(accounts[1].lamports(), 1);
1339
1340 let accounts = process_instruction(
1342 &bincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1343 transaction_accounts.clone(),
1344 instruction_accounts,
1345 Ok(()),
1346 );
1347 assert_eq!(accounts[0].lamports(), 100);
1348 assert_eq!(accounts[1].lamports(), 1);
1349
1350 let accounts = process_instruction(
1352 &bincode::serialize(&SystemInstruction::Transfer { lamports: 0 }).unwrap(),
1353 transaction_accounts,
1354 vec![
1355 AccountMeta {
1356 pubkey: from,
1357 is_signer: false,
1358 is_writable: true,
1359 },
1360 AccountMeta {
1361 pubkey: to,
1362 is_signer: false,
1363 is_writable: true,
1364 },
1365 ],
1366 Err(InstructionError::MissingRequiredSignature),
1367 );
1368 assert_eq!(accounts[0].lamports(), 100);
1369 assert_eq!(accounts[1].lamports(), 1);
1370 }
1371
1372 #[test]
1373 fn test_transfer_with_seed() {
1374 let base = Pubkey::new_unique();
1375 let base_account = AccountSharedData::new(100, 0, &Pubkey::from([2; 32])); let from_seed = "42".to_string();
1377 let from_owner = system_program::id();
1378 let from = Pubkey::create_with_seed(&base, from_seed.as_str(), &from_owner).unwrap();
1379 let from_account = AccountSharedData::new(100, 0, &system_program::id());
1380 let to = Pubkey::from([3; 32]);
1381 let to_account = AccountSharedData::new(1, 0, &to); let transaction_accounts =
1383 vec![(from, from_account), (base, base_account), (to, to_account)];
1384 let instruction_accounts = vec![
1385 AccountMeta {
1386 pubkey: from,
1387 is_signer: true,
1388 is_writable: true,
1389 },
1390 AccountMeta {
1391 pubkey: base,
1392 is_signer: true,
1393 is_writable: false,
1394 },
1395 AccountMeta {
1396 pubkey: to,
1397 is_signer: false,
1398 is_writable: true,
1399 },
1400 ];
1401
1402 let accounts = process_instruction(
1404 &bincode::serialize(&SystemInstruction::TransferWithSeed {
1405 lamports: 50,
1406 from_seed: from_seed.clone(),
1407 from_owner,
1408 })
1409 .unwrap(),
1410 transaction_accounts.clone(),
1411 instruction_accounts.clone(),
1412 Ok(()),
1413 );
1414 assert_eq!(accounts[0].lamports(), 50);
1415 assert_eq!(accounts[2].lamports(), 51);
1416
1417 let accounts = process_instruction(
1419 &bincode::serialize(&SystemInstruction::TransferWithSeed {
1420 lamports: 101,
1421 from_seed: from_seed.clone(),
1422 from_owner,
1423 })
1424 .unwrap(),
1425 transaction_accounts.clone(),
1426 instruction_accounts.clone(),
1427 Err(SystemError::ResultWithNegativeLamports.into()),
1428 );
1429 assert_eq!(accounts[0].lamports(), 100);
1430 assert_eq!(accounts[2].lamports(), 1);
1431
1432 let accounts = process_instruction(
1434 &bincode::serialize(&SystemInstruction::TransferWithSeed {
1435 lamports: 0,
1436 from_seed,
1437 from_owner,
1438 })
1439 .unwrap(),
1440 transaction_accounts,
1441 instruction_accounts,
1442 Ok(()),
1443 );
1444 assert_eq!(accounts[0].lamports(), 100);
1445 assert_eq!(accounts[2].lamports(), 1);
1446 }
1447
1448 #[test]
1449 fn test_transfer_lamports_from_nonce_account_fail() {
1450 let from = Pubkey::new_unique();
1451 let from_account = AccountSharedData::new_data(
1452 100,
1453 &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data {
1454 authority: from,
1455 ..nonce::state::Data::default()
1456 })),
1457 &system_program::id(),
1458 )
1459 .unwrap();
1460 assert_eq!(
1461 get_system_account_kind(&from_account),
1462 Some(SystemAccountKind::Nonce)
1463 );
1464 let to = Pubkey::from([3; 32]);
1465 let to_account = AccountSharedData::new(1, 0, &to); process_instruction(
1468 &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
1469 vec![(from, from_account), (to, to_account)],
1470 vec![
1471 AccountMeta {
1472 pubkey: from,
1473 is_signer: true,
1474 is_writable: false,
1475 },
1476 AccountMeta {
1477 pubkey: to,
1478 is_signer: false,
1479 is_writable: false,
1480 },
1481 ],
1482 Err(InstructionError::InvalidArgument),
1483 );
1484 }
1485
1486 fn process_nonce_instruction(
1487 instruction: Instruction,
1488 expected_result: Result<(), InstructionError>,
1489 ) -> Vec<AccountSharedData> {
1490 let transaction_accounts = instruction
1491 .accounts
1492 .iter()
1493 .map(|meta| {
1494 #[allow(deprecated)]
1495 (
1496 meta.pubkey,
1497 if sysvar::recent_blockhashes::check_id(&meta.pubkey) {
1498 create_default_recent_blockhashes_account()
1499 } else if sysvar::rent::check_id(&meta.pubkey) {
1500 account::create_account_shared_data_for_test(&Rent::free())
1501 } else {
1502 AccountSharedData::new(0, 0, &Pubkey::new_unique())
1503 },
1504 )
1505 })
1506 .collect();
1507 process_instruction(
1508 &instruction.data,
1509 transaction_accounts,
1510 instruction.accounts,
1511 expected_result,
1512 )
1513 }
1514
1515 #[test]
1516 fn test_process_nonce_ix_no_acc_data_fail() {
1517 let none_address = Pubkey::new_unique();
1518 process_nonce_instruction(
1519 system_instruction::advance_nonce_account(&none_address, &none_address),
1520 Err(InstructionError::InvalidAccountData),
1521 );
1522 }
1523
1524 #[test]
1525 fn test_process_nonce_ix_no_keyed_accs_fail() {
1526 process_instruction(
1527 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1528 Vec::new(),
1529 Vec::new(),
1530 Err(InstructionError::NotEnoughAccountKeys),
1531 );
1532 }
1533
1534 #[test]
1535 fn test_process_nonce_ix_only_nonce_acc_fail() {
1536 let pubkey = Pubkey::new_unique();
1537 process_instruction(
1538 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1539 vec![(pubkey, create_default_account())],
1540 vec![AccountMeta {
1541 pubkey,
1542 is_signer: true,
1543 is_writable: true,
1544 }],
1545 Err(InstructionError::NotEnoughAccountKeys),
1546 );
1547 }
1548
1549 #[test]
1550 fn test_process_nonce_ix_ok() {
1551 let nonce_address = Pubkey::new_unique();
1552 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1553 #[allow(deprecated)]
1554 let blockhash_id = sysvar::recent_blockhashes::id();
1555 let accounts = process_instruction(
1556 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1557 vec![
1558 (nonce_address, nonce_account),
1559 (blockhash_id, create_default_recent_blockhashes_account()),
1560 (sysvar::rent::id(), create_default_rent_account()),
1561 ],
1562 vec![
1563 AccountMeta {
1564 pubkey: nonce_address,
1565 is_signer: true,
1566 is_writable: true,
1567 },
1568 AccountMeta {
1569 pubkey: blockhash_id,
1570 is_signer: false,
1571 is_writable: false,
1572 },
1573 AccountMeta {
1574 pubkey: sysvar::rent::id(),
1575 is_signer: false,
1576 is_writable: false,
1577 },
1578 ],
1579 Ok(()),
1580 );
1581 let blockhash = hash(&serialize(&0).unwrap());
1582 #[allow(deprecated)]
1583 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![
1584 IterItem(0u64, &blockhash, 0);
1585 sysvar::recent_blockhashes::MAX_ENTRIES
1586 ]);
1587 mock_process_instruction(
1588 &system_program::id(),
1589 Vec::new(),
1590 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1591 vec![
1592 (nonce_address, accounts[0].clone()),
1593 (blockhash_id, new_recent_blockhashes_account),
1594 ],
1595 vec![
1596 AccountMeta {
1597 pubkey: nonce_address,
1598 is_signer: true,
1599 is_writable: true,
1600 },
1601 AccountMeta {
1602 pubkey: blockhash_id,
1603 is_signer: false,
1604 is_writable: false,
1605 },
1606 ],
1607 Ok(()),
1608 Entrypoint::vm,
1609 |invoke_context: &mut InvokeContext| {
1610 invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1611 },
1612 |_invoke_context| {},
1613 );
1614 }
1615
1616 #[test]
1617 fn test_process_withdraw_ix_no_acc_data_fail() {
1618 let nonce_address = Pubkey::new_unique();
1619 process_nonce_instruction(
1620 system_instruction::withdraw_nonce_account(
1621 &nonce_address,
1622 &Pubkey::new_unique(),
1623 &nonce_address,
1624 1,
1625 ),
1626 Err(InstructionError::InvalidAccountData),
1627 );
1628 }
1629
1630 #[test]
1631 fn test_process_withdraw_ix_no_keyed_accs_fail() {
1632 process_instruction(
1633 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1634 Vec::new(),
1635 Vec::new(),
1636 Err(InstructionError::NotEnoughAccountKeys),
1637 );
1638 }
1639
1640 #[test]
1641 fn test_process_withdraw_ix_only_nonce_acc_fail() {
1642 let nonce_address = Pubkey::new_unique();
1643 process_instruction(
1644 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1645 vec![(nonce_address, create_default_account())],
1646 vec![AccountMeta {
1647 pubkey: nonce_address,
1648 is_signer: true,
1649 is_writable: true,
1650 }],
1651 Err(InstructionError::NotEnoughAccountKeys),
1652 );
1653 }
1654
1655 #[test]
1656 fn test_process_withdraw_ix_ok() {
1657 let nonce_address = Pubkey::new_unique();
1658 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1659 let pubkey = Pubkey::new_unique();
1660 #[allow(deprecated)]
1661 let blockhash_id = sysvar::recent_blockhashes::id();
1662 process_instruction(
1663 &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(),
1664 vec![
1665 (nonce_address, nonce_account),
1666 (pubkey, create_default_account()),
1667 (blockhash_id, create_default_recent_blockhashes_account()),
1668 (sysvar::rent::id(), create_default_rent_account()),
1669 ],
1670 vec![
1671 AccountMeta {
1672 pubkey: nonce_address,
1673 is_signer: true,
1674 is_writable: true,
1675 },
1676 AccountMeta {
1677 pubkey,
1678 is_signer: true,
1679 is_writable: true,
1680 },
1681 AccountMeta {
1682 pubkey: blockhash_id,
1683 is_signer: false,
1684 is_writable: false,
1685 },
1686 AccountMeta {
1687 pubkey: sysvar::rent::id(),
1688 is_signer: false,
1689 is_writable: false,
1690 },
1691 ],
1692 Ok(()),
1693 );
1694 }
1695
1696 #[test]
1697 fn test_process_initialize_ix_no_keyed_accs_fail() {
1698 process_instruction(
1699 &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(),
1700 Vec::new(),
1701 Vec::new(),
1702 Err(InstructionError::NotEnoughAccountKeys),
1703 );
1704 }
1705
1706 #[test]
1707 fn test_process_initialize_ix_only_nonce_acc_fail() {
1708 let nonce_address = Pubkey::new_unique();
1709 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1710 process_instruction(
1711 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1712 vec![(nonce_address, nonce_account)],
1713 vec![AccountMeta {
1714 pubkey: nonce_address,
1715 is_signer: true,
1716 is_writable: true,
1717 }],
1718 Err(InstructionError::NotEnoughAccountKeys),
1719 );
1720 }
1721
1722 #[test]
1723 fn test_process_initialize_ix_ok() {
1724 let nonce_address = Pubkey::new_unique();
1725 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1726 #[allow(deprecated)]
1727 let blockhash_id = sysvar::recent_blockhashes::id();
1728 process_instruction(
1729 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1730 vec![
1731 (nonce_address, nonce_account),
1732 (blockhash_id, create_default_recent_blockhashes_account()),
1733 (sysvar::rent::id(), create_default_rent_account()),
1734 ],
1735 vec![
1736 AccountMeta {
1737 pubkey: nonce_address,
1738 is_signer: true,
1739 is_writable: true,
1740 },
1741 AccountMeta {
1742 pubkey: blockhash_id,
1743 is_signer: false,
1744 is_writable: false,
1745 },
1746 AccountMeta {
1747 pubkey: sysvar::rent::id(),
1748 is_signer: false,
1749 is_writable: false,
1750 },
1751 ],
1752 Ok(()),
1753 );
1754 }
1755
1756 #[test]
1757 fn test_process_authorize_ix_ok() {
1758 let nonce_address = Pubkey::new_unique();
1759 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1760 #[allow(deprecated)]
1761 let blockhash_id = sysvar::recent_blockhashes::id();
1762 let accounts = process_instruction(
1763 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1764 vec![
1765 (nonce_address, nonce_account),
1766 (blockhash_id, create_default_recent_blockhashes_account()),
1767 (sysvar::rent::id(), create_default_rent_account()),
1768 ],
1769 vec![
1770 AccountMeta {
1771 pubkey: nonce_address,
1772 is_signer: true,
1773 is_writable: true,
1774 },
1775 AccountMeta {
1776 pubkey: blockhash_id,
1777 is_signer: false,
1778 is_writable: false,
1779 },
1780 AccountMeta {
1781 pubkey: sysvar::rent::id(),
1782 is_signer: false,
1783 is_writable: false,
1784 },
1785 ],
1786 Ok(()),
1787 );
1788 process_instruction(
1789 &serialize(&SystemInstruction::AuthorizeNonceAccount(nonce_address)).unwrap(),
1790 vec![(nonce_address, accounts[0].clone())],
1791 vec![AccountMeta {
1792 pubkey: nonce_address,
1793 is_signer: true,
1794 is_writable: true,
1795 }],
1796 Ok(()),
1797 );
1798 }
1799
1800 #[test]
1801 fn test_process_authorize_bad_account_data_fail() {
1802 let nonce_address = Pubkey::new_unique();
1803 process_nonce_instruction(
1804 system_instruction::authorize_nonce_account(
1805 &nonce_address,
1806 &Pubkey::new_unique(),
1807 &nonce_address,
1808 ),
1809 Err(InstructionError::InvalidAccountData),
1810 );
1811 }
1812
1813 #[test]
1814 fn test_nonce_initialize_with_empty_recent_blockhashes_fail() {
1815 let nonce_address = Pubkey::new_unique();
1816 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1817 #[allow(deprecated)]
1818 let blockhash_id = sysvar::recent_blockhashes::id();
1819 #[allow(deprecated)]
1820 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1821 process_instruction(
1822 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1823 vec![
1824 (nonce_address, nonce_account),
1825 (blockhash_id, new_recent_blockhashes_account),
1826 (sysvar::rent::id(), create_default_rent_account()),
1827 ],
1828 vec![
1829 AccountMeta {
1830 pubkey: nonce_address,
1831 is_signer: true,
1832 is_writable: true,
1833 },
1834 AccountMeta {
1835 pubkey: blockhash_id,
1836 is_signer: false,
1837 is_writable: false,
1838 },
1839 AccountMeta {
1840 pubkey: sysvar::rent::id(),
1841 is_signer: false,
1842 is_writable: false,
1843 },
1844 ],
1845 Err(SystemError::NonceNoRecentBlockhashes.into()),
1846 );
1847 }
1848
1849 #[test]
1850 fn test_nonce_advance_with_empty_recent_blockhashes_fail() {
1851 let nonce_address = Pubkey::new_unique();
1852 let nonce_account = nonce_account::create_account(1_000_000).into_inner();
1853 #[allow(deprecated)]
1854 let blockhash_id = sysvar::recent_blockhashes::id();
1855 let accounts = process_instruction(
1856 &serialize(&SystemInstruction::InitializeNonceAccount(nonce_address)).unwrap(),
1857 vec![
1858 (nonce_address, nonce_account),
1859 (blockhash_id, create_default_recent_blockhashes_account()),
1860 (sysvar::rent::id(), create_default_rent_account()),
1861 ],
1862 vec![
1863 AccountMeta {
1864 pubkey: nonce_address,
1865 is_signer: true,
1866 is_writable: true,
1867 },
1868 AccountMeta {
1869 pubkey: blockhash_id,
1870 is_signer: false,
1871 is_writable: false,
1872 },
1873 AccountMeta {
1874 pubkey: sysvar::rent::id(),
1875 is_signer: false,
1876 is_writable: false,
1877 },
1878 ],
1879 Ok(()),
1880 );
1881 #[allow(deprecated)]
1882 let new_recent_blockhashes_account = create_recent_blockhashes_account_for_test(vec![]);
1883 mock_process_instruction(
1884 &system_program::id(),
1885 Vec::new(),
1886 &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(),
1887 vec![
1888 (nonce_address, accounts[0].clone()),
1889 (blockhash_id, new_recent_blockhashes_account),
1890 ],
1891 vec![
1892 AccountMeta {
1893 pubkey: nonce_address,
1894 is_signer: true,
1895 is_writable: true,
1896 },
1897 AccountMeta {
1898 pubkey: blockhash_id,
1899 is_signer: false,
1900 is_writable: false,
1901 },
1902 ],
1903 Err(SystemError::NonceNoRecentBlockhashes.into()),
1904 Entrypoint::vm,
1905 |invoke_context: &mut InvokeContext| {
1906 invoke_context.environment_config.blockhash = hash(&serialize(&0).unwrap());
1907 },
1908 |_invoke_context| {},
1909 );
1910 }
1911
1912 #[test]
1913 fn test_nonce_account_upgrade_check_owner() {
1914 let nonce_address = Pubkey::new_unique();
1915 let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1916 let nonce_account = AccountSharedData::new_data(
1917 1_000_000, &versions, &Pubkey::new_unique(), )
1921 .unwrap();
1922 let accounts = process_instruction(
1923 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1924 vec![(nonce_address, nonce_account.clone())],
1925 vec![AccountMeta {
1926 pubkey: nonce_address,
1927 is_signer: false,
1928 is_writable: true,
1929 }],
1930 Err(InstructionError::InvalidAccountOwner),
1931 );
1932 assert_eq!(accounts.len(), 1);
1933 assert_eq!(accounts[0], nonce_account);
1934 }
1935
1936 fn new_nonce_account(versions: NonceVersions) -> AccountSharedData {
1937 let nonce_account = AccountSharedData::new_data(
1938 1_000_000, &versions, &system_program::id(), )
1942 .unwrap();
1943 assert_eq!(
1944 nonce_account.deserialize_data::<NonceVersions>().unwrap(),
1945 versions
1946 );
1947 nonce_account
1948 }
1949
1950 #[test]
1951 fn test_nonce_account_upgrade() {
1952 let nonce_address = Pubkey::new_unique();
1953 let versions = NonceVersions::Legacy(Box::new(NonceState::Uninitialized));
1954 let nonce_account = new_nonce_account(versions);
1955 let accounts = process_instruction(
1956 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1957 vec![(nonce_address, nonce_account.clone())],
1958 vec![AccountMeta {
1959 pubkey: nonce_address,
1960 is_signer: false,
1961 is_writable: true,
1962 }],
1963 Err(InstructionError::InvalidArgument),
1964 );
1965 assert_eq!(accounts.len(), 1);
1966 assert_eq!(accounts[0], nonce_account);
1967 let versions = NonceVersions::Current(Box::new(NonceState::Uninitialized));
1968 let nonce_account = new_nonce_account(versions);
1969 let accounts = process_instruction(
1970 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
1971 vec![(nonce_address, nonce_account.clone())],
1972 vec![AccountMeta {
1973 pubkey: nonce_address,
1974 is_signer: false,
1975 is_writable: true,
1976 }],
1977 Err(InstructionError::InvalidArgument),
1978 );
1979 assert_eq!(accounts.len(), 1);
1980 assert_eq!(accounts[0], nonce_account);
1981 let blockhash = Hash::from([171; 32]);
1982 let durable_nonce = DurableNonce::from_blockhash(&blockhash);
1983 let data = NonceData {
1984 authority: Pubkey::new_unique(),
1985 durable_nonce,
1986 fee_calculator: FeeCalculator {
1987 lamports_per_signature: 2718,
1988 },
1989 };
1990 let versions = NonceVersions::Legacy(Box::new(NonceState::Initialized(data.clone())));
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: false, }],
2000 Err(InstructionError::InvalidArgument),
2001 );
2002 assert_eq!(accounts.len(), 1);
2003 assert_eq!(accounts[0], nonce_account);
2004 let mut accounts = process_instruction(
2005 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2006 vec![(nonce_address, nonce_account)],
2007 vec![AccountMeta {
2008 pubkey: nonce_address,
2009 is_signer: false,
2010 is_writable: true,
2011 }],
2012 Ok(()),
2013 );
2014 assert_eq!(accounts.len(), 1);
2015 let nonce_account = accounts.remove(0);
2016 let durable_nonce = DurableNonce::from_blockhash(durable_nonce.as_hash());
2017 assert_ne!(data.durable_nonce, durable_nonce);
2018 let data = NonceData {
2019 durable_nonce,
2020 ..data
2021 };
2022 let upgraded_nonce_account =
2023 NonceVersions::Current(Box::new(NonceState::Initialized(data)));
2024 assert_eq!(
2025 nonce_account.deserialize_data::<NonceVersions>().unwrap(),
2026 upgraded_nonce_account
2027 );
2028 let accounts = process_instruction(
2029 &serialize(&SystemInstruction::UpgradeNonceAccount).unwrap(),
2030 vec![(nonce_address, nonce_account)],
2031 vec![AccountMeta {
2032 pubkey: nonce_address,
2033 is_signer: false,
2034 is_writable: true,
2035 }],
2036 Err(InstructionError::InvalidArgument),
2037 );
2038 assert_eq!(accounts.len(), 1);
2039 assert_eq!(
2040 accounts[0].deserialize_data::<NonceVersions>().unwrap(),
2041 upgraded_nonce_account
2042 );
2043 }
2044
2045 #[test]
2046 fn test_assign_native_loader_and_transfer() {
2047 for size in [0, 10] {
2048 let pubkey = Pubkey::new_unique();
2049 let account = AccountSharedData::new(100, size, &system_program::id());
2050 let accounts = process_instruction(
2051 &bincode::serialize(&SystemInstruction::Assign {
2052 owner: solana_sdk::native_loader::id(),
2053 })
2054 .unwrap(),
2055 vec![(pubkey, account.clone())],
2056 vec![AccountMeta {
2057 pubkey,
2058 is_signer: true,
2059 is_writable: true,
2060 }],
2061 Ok(()),
2062 );
2063 assert_eq!(accounts[0].owner(), &solana_sdk::native_loader::id());
2064 assert_eq!(accounts[0].lamports(), 100);
2065
2066 let pubkey2 = Pubkey::new_unique();
2067 let accounts = process_instruction(
2068 &bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
2069 vec![
2070 (
2071 pubkey2,
2072 AccountSharedData::new(100, 0, &system_program::id()),
2073 ),
2074 (pubkey, accounts[0].clone()),
2075 ],
2076 vec![
2077 AccountMeta {
2078 pubkey: pubkey2,
2079 is_signer: true,
2080 is_writable: true,
2081 },
2082 AccountMeta {
2083 pubkey,
2084 is_signer: false,
2085 is_writable: true,
2086 },
2087 ],
2088 Ok(()),
2089 );
2090 assert_eq!(accounts[1].owner(), &solana_sdk::native_loader::id());
2091 assert_eq!(accounts[1].lamports(), 150);
2092 }
2093 }
2094}