1use crate::{
2 accounts_db::{
3 AccountShrinkThreshold, AccountsDb, AccountsDbConfig, BankHashInfo, ErrorCounters,
4 LoadHint, LoadedAccount, ScanStorageResult, ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS,
5 ACCOUNTS_DB_CONFIG_FOR_TESTING,
6 },
7 accounts_index::{AccountSecondaryIndexes, IndexKey, ScanResult},
8 ancestors::Ancestors,
9 bank::{
10 NonceRollbackFull, NonceRollbackInfo, RentDebits, TransactionCheckResult,
11 TransactionExecutionResult,
12 },
13 blockhash_queue::BlockhashQueue,
14 rent_collector::RentCollector,
15 system_instruction_processor::{get_system_account_kind, SystemAccountKind},
16};
17use dashmap::{
18 mapref::entry::Entry::{Occupied, Vacant},
19 DashMap,
20};
21use log::*;
22use rand::{thread_rng, Rng};
23use gemachain_sdk::{
24 account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
25 account_utils::StateMut,
26 bpf_loader_upgradeable::{self, UpgradeableLoaderState},
27 clock::{BankId, Slot, INITIAL_RENT_EPOCH},
28 feature_set::{self, FeatureSet},
29 fee_calculator::FeeCalculator,
30 genesis_config::ClusterType,
31 hash::Hash,
32 message::SanitizedMessage,
33 native_loader, nonce,
34 nonce::NONCED_TX_MARKER_IX_INDEX,
35 pubkey::Pubkey,
36 system_program, sysvar,
37 transaction::{Result, SanitizedTransaction, TransactionError},
38};
39use std::{
40 cmp::Reverse,
41 collections::{hash_map, BinaryHeap, HashMap, HashSet},
42 ops::RangeBounds,
43 path::PathBuf,
44 sync::{Arc, Mutex},
45};
46
47#[derive(Debug, Default, AbiExample)]
48pub struct AccountLocks {
49 write_locks: HashSet<Pubkey>,
50 readonly_locks: HashMap<Pubkey, u64>,
51}
52
53impl AccountLocks {
54 fn is_locked_readonly(&self, key: &Pubkey) -> bool {
55 self.readonly_locks
56 .get(key)
57 .map_or(false, |count| *count > 0)
58 }
59
60 fn is_locked_write(&self, key: &Pubkey) -> bool {
61 self.write_locks.contains(key)
62 }
63
64 fn insert_new_readonly(&mut self, key: &Pubkey) {
65 assert!(self.readonly_locks.insert(*key, 1).is_none());
66 }
67
68 fn lock_readonly(&mut self, key: &Pubkey) -> bool {
69 self.readonly_locks.get_mut(key).map_or(false, |count| {
70 *count += 1;
71 true
72 })
73 }
74
75 fn unlock_readonly(&mut self, key: &Pubkey) {
76 if let hash_map::Entry::Occupied(mut occupied_entry) = self.readonly_locks.entry(*key) {
77 let count = occupied_entry.get_mut();
78 *count -= 1;
79 if *count == 0 {
80 occupied_entry.remove_entry();
81 }
82 }
83 }
84
85 fn unlock_write(&mut self, key: &Pubkey) {
86 self.write_locks.remove(key);
87 }
88}
89
90#[derive(Debug, AbiExample)]
92pub struct Accounts {
93 pub accounts_db: Arc<AccountsDb>,
95
96 pub(crate) account_locks: Mutex<AccountLocks>,
99}
100
101pub type TransactionAccounts = Vec<(Pubkey, AccountSharedData)>;
103pub type TransactionRent = u64;
104pub type TransactionProgramIndices = Vec<Vec<usize>>;
105#[derive(PartialEq, Debug, Clone)]
106pub struct LoadedTransaction {
107 pub accounts: TransactionAccounts,
108 pub program_indices: TransactionProgramIndices,
109 pub rent: TransactionRent,
110 pub rent_debits: RentDebits,
111}
112
113pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceRollbackFull>);
114
115pub enum AccountAddressFilter {
116 Exclude, Include, }
119
120impl Accounts {
121 pub fn default_for_tests() -> Self {
122 Self {
123 accounts_db: Arc::new(AccountsDb::default_for_tests()),
124 account_locks: Mutex::default(),
125 }
126 }
127
128 pub fn new_with_config_for_tests(
129 paths: Vec<PathBuf>,
130 cluster_type: &ClusterType,
131 account_indexes: AccountSecondaryIndexes,
132 caching_enabled: bool,
133 shrink_ratio: AccountShrinkThreshold,
134 ) -> Self {
135 Self::new_with_config(
136 paths,
137 cluster_type,
138 account_indexes,
139 caching_enabled,
140 shrink_ratio,
141 Some(ACCOUNTS_DB_CONFIG_FOR_TESTING),
142 )
143 }
144
145 pub fn new_with_config_for_benches(
146 paths: Vec<PathBuf>,
147 cluster_type: &ClusterType,
148 account_indexes: AccountSecondaryIndexes,
149 caching_enabled: bool,
150 shrink_ratio: AccountShrinkThreshold,
151 ) -> Self {
152 Self::new_with_config(
153 paths,
154 cluster_type,
155 account_indexes,
156 caching_enabled,
157 shrink_ratio,
158 Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
159 )
160 }
161
162 pub fn new_with_config(
163 paths: Vec<PathBuf>,
164 cluster_type: &ClusterType,
165 account_indexes: AccountSecondaryIndexes,
166 caching_enabled: bool,
167 shrink_ratio: AccountShrinkThreshold,
168 accounts_db_config: Option<AccountsDbConfig>,
169 ) -> Self {
170 Self {
171 accounts_db: Arc::new(AccountsDb::new_with_config(
172 paths,
173 cluster_type,
174 account_indexes,
175 caching_enabled,
176 shrink_ratio,
177 accounts_db_config,
178 )),
179 account_locks: Mutex::new(AccountLocks::default()),
180 }
181 }
182
183 pub fn new_from_parent(parent: &Accounts, slot: Slot, parent_slot: Slot) -> Self {
184 let accounts_db = parent.accounts_db.clone();
185 accounts_db.set_hash(slot, parent_slot);
186 Self {
187 accounts_db,
188 account_locks: Mutex::new(AccountLocks::default()),
189 }
190 }
191
192 pub(crate) fn new_empty(accounts_db: AccountsDb) -> Self {
193 Self {
194 accounts_db: Arc::new(accounts_db),
195 account_locks: Mutex::new(AccountLocks::default()),
196 }
197 }
198
199 fn construct_instructions_account(
200 message: &SanitizedMessage,
201 is_owned_by_sysvar: bool,
202 demote_program_write_locks: bool,
203 ) -> AccountSharedData {
204 let mut data = message.serialize_instructions(demote_program_write_locks);
205 data.resize(data.len() + 2, 0);
207 let owner = if is_owned_by_sysvar {
208 sysvar::id()
209 } else {
210 system_program::id()
211 };
212 AccountSharedData::from(Account {
213 data,
214 owner,
215 ..Account::default()
216 })
217 }
218
219 fn load_transaction(
220 &self,
221 ancestors: &Ancestors,
222 tx: &SanitizedTransaction,
223 fee: u64,
224 error_counters: &mut ErrorCounters,
225 rent_collector: &RentCollector,
226 feature_set: &FeatureSet,
227 ) -> Result<LoadedTransaction> {
228 let message = tx.message();
230 if tx.signatures().is_empty() && fee != 0 {
232 Err(TransactionError::MissingSignatureForFee)
233 } else {
234 let mut payer_index = None;
237 let mut tx_rent: TransactionRent = 0;
238 let mut accounts = Vec::with_capacity(message.account_keys_len());
239 let mut account_deps = Vec::with_capacity(message.account_keys_len());
240 let mut rent_debits = RentDebits::default();
241 let rent_for_sysvars = feature_set.is_active(&feature_set::rent_for_sysvars::id());
242 let demote_program_write_locks =
243 feature_set.is_active(&feature_set::demote_program_write_locks::id());
244 let is_upgradeable_loader_present = is_upgradeable_loader_present(message);
245
246 for (i, key) in message.account_keys_iter().enumerate() {
247 let account = if !message.is_non_loader_key(i) {
248 AccountSharedData::default()
250 } else {
251 if payer_index.is_none() {
252 payer_index = Some(i);
253 }
254
255 if gemachain_sdk::sysvar::instructions::check_id(key) {
256 Self::construct_instructions_account(
257 message,
258 feature_set
259 .is_active(&feature_set::instructions_sysvar_owned_by_sysvar::id()),
260 demote_program_write_locks,
261 )
262 } else {
263 let (account, rent) = self
264 .accounts_db
265 .load_with_fixed_root(ancestors, key)
266 .map(|(mut account, _)| {
267 if message.is_writable(i, demote_program_write_locks) {
268 let rent_due = rent_collector.collect_from_existing_account(
269 key,
270 &mut account,
271 rent_for_sysvars,
272 );
273 (account, rent_due)
274 } else {
275 (account, 0)
276 }
277 })
278 .unwrap_or_default();
279
280 if bpf_loader_upgradeable::check_id(account.owner()) {
281 if demote_program_write_locks
282 && message.is_writable(i, demote_program_write_locks)
283 && !is_upgradeable_loader_present
284 {
285 error_counters.invalid_writable_account += 1;
286 return Err(TransactionError::InvalidWritableAccount);
287 }
288
289 if account.executable() {
290 if let Ok(UpgradeableLoaderState::Program {
292 programdata_address,
293 }) = account.state()
294 {
295 if let Some((programdata_account, _)) = self
296 .accounts_db
297 .load_with_fixed_root(ancestors, &programdata_address)
298 {
299 account_deps
300 .push((programdata_address, programdata_account));
301 } else {
302 error_counters.account_not_found += 1;
303 return Err(TransactionError::ProgramAccountNotFound);
304 }
305 } else {
306 error_counters.invalid_program_for_execution += 1;
307 return Err(TransactionError::InvalidProgramForExecution);
308 }
309 }
310 } else if account.executable()
311 && demote_program_write_locks
312 && message.is_writable(i, demote_program_write_locks)
313 {
314 error_counters.invalid_writable_account += 1;
315 return Err(TransactionError::InvalidWritableAccount);
316 }
317
318 tx_rent += rent;
319 rent_debits.push(key, rent, account.carats());
320
321 account
322 }
323 };
324 accounts.push((*key, account));
325 }
326 debug_assert_eq!(accounts.len(), message.account_keys_len());
327 accounts.append(&mut account_deps);
333
334 if let Some(payer_index) = payer_index {
335 if payer_index != 0 {
336 warn!("Payer index should be 0! {:?}", tx);
337 }
338 let payer_account = &mut accounts[payer_index].1;
339 if payer_account.carats() == 0 {
340 error_counters.account_not_found += 1;
341 return Err(TransactionError::AccountNotFound);
342 }
343 let min_balance = match get_system_account_kind(payer_account).ok_or_else(|| {
344 error_counters.invalid_account_for_fee += 1;
345 TransactionError::InvalidAccountForFee
346 })? {
347 SystemAccountKind::System => 0,
348 SystemAccountKind::Nonce => {
349 rent_collector.rent.minimum_balance(nonce::State::size())
352 }
353 };
354
355 if payer_account.carats() < fee + min_balance {
356 error_counters.insufficient_funds += 1;
357 return Err(TransactionError::InsufficientFundsForFee);
358 }
359 payer_account
360 .checked_sub_carats(fee)
361 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
362
363 let program_indices = message
364 .instructions()
365 .iter()
366 .map(|instruction| {
367 self.load_executable_accounts(
368 ancestors,
369 &mut accounts,
370 instruction.program_id_index as usize,
371 error_counters,
372 )
373 })
374 .collect::<Result<Vec<Vec<usize>>>>()?;
375 Ok(LoadedTransaction {
376 accounts,
377 program_indices,
378 rent: tx_rent,
379 rent_debits,
380 })
381 } else {
382 error_counters.account_not_found += 1;
383 Err(TransactionError::AccountNotFound)
384 }
385 }
386 }
387
388 fn load_executable_accounts(
389 &self,
390 ancestors: &Ancestors,
391 accounts: &mut Vec<(Pubkey, AccountSharedData)>,
392 mut program_account_index: usize,
393 error_counters: &mut ErrorCounters,
394 ) -> Result<Vec<usize>> {
395 let mut account_indices = Vec::new();
396 let mut program_id = accounts[program_account_index].0;
397 let mut depth = 0;
398 while !native_loader::check_id(&program_id) {
399 if depth >= 5 {
400 error_counters.call_chain_too_deep += 1;
401 return Err(TransactionError::CallChainTooDeep);
402 }
403 depth += 1;
404
405 program_account_index = match self
406 .accounts_db
407 .load_with_fixed_root(ancestors, &program_id)
408 {
409 Some((program_account, _)) => {
410 let account_index = accounts.len();
411 accounts.push((program_id, program_account));
412 account_index
413 }
414 None => {
415 error_counters.account_not_found += 1;
416 return Err(TransactionError::ProgramAccountNotFound);
417 }
418 };
419 let program = &accounts[program_account_index].1;
420 if !program.executable() {
421 error_counters.invalid_program_for_execution += 1;
422 return Err(TransactionError::InvalidProgramForExecution);
423 }
424
425 let program_owner = *program.owner();
427
428 if bpf_loader_upgradeable::check_id(&program_owner) {
429 if let Ok(UpgradeableLoaderState::Program {
431 programdata_address,
432 }) = program.state()
433 {
434 let programdata_account_index = match self
435 .accounts_db
436 .load_with_fixed_root(ancestors, &programdata_address)
437 {
438 Some((programdata_account, _)) => {
439 let account_index = accounts.len();
440 accounts.push((programdata_address, programdata_account));
441 account_index
442 }
443 None => {
444 error_counters.account_not_found += 1;
445 return Err(TransactionError::ProgramAccountNotFound);
446 }
447 };
448 account_indices.insert(0, programdata_account_index);
449 } else {
450 error_counters.invalid_program_for_execution += 1;
451 return Err(TransactionError::InvalidProgramForExecution);
452 }
453 }
454
455 account_indices.insert(0, program_account_index);
456 program_id = program_owner;
457 }
458 Ok(account_indices)
459 }
460
461 pub fn load_accounts(
462 &self,
463 ancestors: &Ancestors,
464 txs: &[SanitizedTransaction],
465 lock_results: Vec<TransactionCheckResult>,
466 hash_queue: &BlockhashQueue,
467 error_counters: &mut ErrorCounters,
468 rent_collector: &RentCollector,
469 feature_set: &FeatureSet,
470 ) -> Vec<TransactionLoadResult> {
471 txs.iter()
472 .zip(lock_results)
473 .map(|etx| match etx {
474 (tx, (Ok(()), nonce_rollback)) => {
475 let fee_calculator = nonce_rollback
476 .as_ref()
477 .map(|nonce_rollback| nonce_rollback.fee_calculator())
478 .unwrap_or_else(|| {
479 #[allow(deprecated)]
480 hash_queue
481 .get_fee_calculator(tx.message().recent_blockhash())
482 .cloned()
483 });
484 let fee = if let Some(fee_calculator) = fee_calculator {
485 tx.message().calculate_fee(&fee_calculator)
486 } else {
487 return (Err(TransactionError::BlockhashNotFound), None);
488 };
489
490 let loaded_transaction = match self.load_transaction(
491 ancestors,
492 tx,
493 fee,
494 error_counters,
495 rent_collector,
496 feature_set,
497 ) {
498 Ok(loaded_transaction) => loaded_transaction,
499 Err(e) => return (Err(e), None),
500 };
501
502 let nonce_rollback = if let Some(nonce_rollback) = nonce_rollback {
504 match NonceRollbackFull::from_partial(
505 nonce_rollback,
506 tx.message(),
507 &loaded_transaction.accounts,
508 ) {
509 Ok(nonce_rollback) => Some(nonce_rollback),
510 Err(e) => return (Err(e), None),
511 }
512 } else {
513 None
514 };
515
516 (Ok(loaded_transaction), nonce_rollback)
517 }
518 (_, (Err(e), _nonce_rollback)) => (Err(e), None),
519 })
520 .collect()
521 }
522
523 fn filter_zero_carat_account(
524 account: AccountSharedData,
525 slot: Slot,
526 ) -> Option<(AccountSharedData, Slot)> {
527 if account.carats() > 0 {
528 Some((account, slot))
529 } else {
530 None
531 }
532 }
533
534 fn load_slow(
536 &self,
537 ancestors: &Ancestors,
538 pubkey: &Pubkey,
539 load_hint: LoadHint,
540 ) -> Option<(AccountSharedData, Slot)> {
541 let (account, slot) = self.accounts_db.load(ancestors, pubkey, load_hint)?;
542 Self::filter_zero_carat_account(account, slot)
543 }
544
545 pub fn load_with_fixed_root(
546 &self,
547 ancestors: &Ancestors,
548 pubkey: &Pubkey,
549 ) -> Option<(AccountSharedData, Slot)> {
550 self.load_slow(ancestors, pubkey, LoadHint::FixedMaxRoot)
551 }
552
553 pub fn load_without_fixed_root(
554 &self,
555 ancestors: &Ancestors,
556 pubkey: &Pubkey,
557 ) -> Option<(AccountSharedData, Slot)> {
558 self.load_slow(ancestors, pubkey, LoadHint::Unspecified)
559 }
560
561 pub fn scan_slot<F, B>(&self, slot: Slot, func: F) -> Vec<B>
565 where
566 F: Fn(LoadedAccount) -> Option<B> + Send + Sync,
567 B: Sync + Send + Default + std::cmp::Eq,
568 {
569 let scan_result = self.accounts_db.scan_account_storage(
570 slot,
571 |loaded_account: LoadedAccount| {
572 func(loaded_account)
574 },
575 |accum: &DashMap<Pubkey, (u64, B)>, loaded_account: LoadedAccount| {
576 let loaded_account_pubkey = *loaded_account.pubkey();
577 let loaded_write_version = loaded_account.write_version();
578 let should_insert = accum
579 .get(&loaded_account_pubkey)
580 .map(|existing_entry| loaded_write_version > existing_entry.value().0)
581 .unwrap_or(true);
582 if should_insert {
583 if let Some(val) = func(loaded_account) {
584 match accum.entry(loaded_account_pubkey) {
586 Occupied(mut occupied_entry) => {
588 if loaded_write_version > occupied_entry.get().0 {
589 occupied_entry.insert((loaded_write_version, val));
590 }
591 }
592
593 Vacant(vacant_entry) => {
594 vacant_entry.insert((loaded_write_version, val));
595 }
596 }
597 }
598 }
599 },
600 );
601
602 match scan_result {
603 ScanStorageResult::Cached(cached_result) => cached_result,
604 ScanStorageResult::Stored(stored_result) => stored_result
605 .into_iter()
606 .map(|(_pubkey, (_latest_write_version, val))| val)
607 .collect(),
608 }
609 }
610
611 pub fn load_by_program_slot(
612 &self,
613 slot: Slot,
614 program_id: Option<&Pubkey>,
615 ) -> Vec<(Pubkey, AccountSharedData)> {
616 self.scan_slot(slot, |stored_account| {
617 let hit = match program_id {
618 None => true,
619 Some(program_id) => stored_account.owner() == program_id,
620 };
621
622 if hit {
623 Some((*stored_account.pubkey(), stored_account.take_account()))
624 } else {
625 None
626 }
627 })
628 }
629
630 pub fn load_largest_accounts(
631 &self,
632 ancestors: &Ancestors,
633 bank_id: BankId,
634 num: usize,
635 filter_by_address: &HashSet<Pubkey>,
636 filter: AccountAddressFilter,
637 ) -> ScanResult<Vec<(Pubkey, u64)>> {
638 if num == 0 {
639 return Ok(vec![]);
640 }
641 let account_balances = self.accounts_db.scan_accounts(
642 ancestors,
643 bank_id,
644 |collector: &mut BinaryHeap<Reverse<(u64, Pubkey)>>, option| {
645 if let Some((pubkey, account, _slot)) = option {
646 if account.carats() == 0 {
647 return;
648 }
649 let contains_address = filter_by_address.contains(pubkey);
650 let collect = match filter {
651 AccountAddressFilter::Exclude => !contains_address,
652 AccountAddressFilter::Include => contains_address,
653 };
654 if !collect {
655 return;
656 }
657 if collector.len() == num {
658 let Reverse(entry) = collector
659 .peek()
660 .expect("BinaryHeap::peek should succeed when len > 0");
661 if *entry >= (account.carats(), *pubkey) {
662 return;
663 }
664 collector.pop();
665 }
666 collector.push(Reverse((account.carats(), *pubkey)));
667 }
668 },
669 )?;
670 Ok(account_balances
671 .into_sorted_vec()
672 .into_iter()
673 .map(|Reverse((balance, pubkey))| (pubkey, balance))
674 .collect())
675 }
676
677 pub fn calculate_capitalization(
678 &self,
679 ancestors: &Ancestors,
680 slot: Slot,
681 can_cached_slot_be_unflushed: bool,
682 debug_verify: bool,
683 ) -> u64 {
684 let use_index = false;
685 self.accounts_db
686 .update_accounts_hash_with_index_option(
687 use_index,
688 debug_verify,
689 slot,
690 ancestors,
691 None,
692 can_cached_slot_be_unflushed,
693 None,
694 )
695 .1
696 }
697
698 #[must_use]
699 pub fn verify_bank_hash_and_carats(
700 &self,
701 slot: Slot,
702 ancestors: &Ancestors,
703 total_carats: u64,
704 test_hash_calculation: bool,
705 ) -> bool {
706 if let Err(err) = self.accounts_db.verify_bank_hash_and_carats(
707 slot,
708 ancestors,
709 total_carats,
710 test_hash_calculation,
711 ) {
712 warn!("verify_bank_hash failed: {:?}", err);
713 false
714 } else {
715 true
716 }
717 }
718
719 fn is_loadable(carats: u64) -> bool {
720 carats > 0
723 }
724
725 fn load_while_filtering<F: Fn(&AccountSharedData) -> bool>(
726 collector: &mut Vec<(Pubkey, AccountSharedData)>,
727 some_account_tuple: Option<(&Pubkey, AccountSharedData, Slot)>,
728 filter: F,
729 ) {
730 if let Some(mapped_account_tuple) = some_account_tuple
731 .filter(|(_, account, _)| Self::is_loadable(account.carats()) && filter(account))
732 .map(|(pubkey, account, _slot)| (*pubkey, account))
733 {
734 collector.push(mapped_account_tuple)
735 }
736 }
737
738 pub fn load_by_program(
739 &self,
740 ancestors: &Ancestors,
741 bank_id: BankId,
742 program_id: &Pubkey,
743 ) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
744 self.accounts_db.scan_accounts(
745 ancestors,
746 bank_id,
747 |collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
748 Self::load_while_filtering(collector, some_account_tuple, |account| {
749 account.owner() == program_id
750 })
751 },
752 )
753 }
754
755 pub fn load_by_program_with_filter<F: Fn(&AccountSharedData) -> bool>(
756 &self,
757 ancestors: &Ancestors,
758 bank_id: BankId,
759 program_id: &Pubkey,
760 filter: F,
761 ) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
762 self.accounts_db.scan_accounts(
763 ancestors,
764 bank_id,
765 |collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
766 Self::load_while_filtering(collector, some_account_tuple, |account| {
767 account.owner() == program_id && filter(account)
768 })
769 },
770 )
771 }
772
773 pub fn load_by_index_key_with_filter<F: Fn(&AccountSharedData) -> bool>(
774 &self,
775 ancestors: &Ancestors,
776 bank_id: BankId,
777 index_key: &IndexKey,
778 filter: F,
779 ) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
780 self.accounts_db
781 .index_scan_accounts(
782 ancestors,
783 bank_id,
784 *index_key,
785 |collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
786 Self::load_while_filtering(collector, some_account_tuple, |account| {
787 filter(account)
788 })
789 },
790 )
791 .map(|result| result.0)
792 }
793
794 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
795 self.accounts_db.account_indexes.include_key(key)
796 }
797
798 pub fn load_all(
799 &self,
800 ancestors: &Ancestors,
801 bank_id: BankId,
802 ) -> ScanResult<Vec<(Pubkey, AccountSharedData, Slot)>> {
803 self.accounts_db.scan_accounts(
804 ancestors,
805 bank_id,
806 |collector: &mut Vec<(Pubkey, AccountSharedData, Slot)>, some_account_tuple| {
807 if let Some((pubkey, account, slot)) = some_account_tuple
808 .filter(|(_, account, _)| Self::is_loadable(account.carats()))
809 {
810 collector.push((*pubkey, account, slot))
811 }
812 },
813 )
814 }
815
816 pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool)
817 where
818 R: RangeBounds<Pubkey> + std::fmt::Debug,
819 {
820 self.accounts_db
821 .accounts_index
822 .hold_range_in_memory(range, start_holding)
823 }
824
825 pub fn load_to_collect_rent_eagerly<R: RangeBounds<Pubkey> + std::fmt::Debug>(
826 &self,
827 ancestors: &Ancestors,
828 range: R,
829 ) -> Vec<(Pubkey, AccountSharedData)> {
830 self.accounts_db.range_scan_accounts(
831 "load_to_collect_rent_eagerly_scan_elapsed",
832 ancestors,
833 range,
834 true,
835 |collector: &mut Vec<(Pubkey, AccountSharedData)>, option| {
836 Self::load_while_filtering(collector, option, |_| true)
837 },
838 )
839 }
840
841 pub fn store_slow_uncached(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData) {
845 self.accounts_db.store_uncached(slot, &[(pubkey, account)]);
846 }
847
848 pub fn store_slow_cached(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData) {
849 self.accounts_db.store_cached(slot, &[(pubkey, account)]);
850 }
851
852 fn lock_account(
853 &self,
854 account_locks: &mut AccountLocks,
855 writable_keys: Vec<&Pubkey>,
856 readonly_keys: Vec<&Pubkey>,
857 ) -> Result<()> {
858 for k in writable_keys.iter() {
859 if account_locks.is_locked_write(k) || account_locks.is_locked_readonly(k) {
860 debug!("Writable account in use: {:?}", k);
861 return Err(TransactionError::AccountInUse);
862 }
863 }
864 for k in readonly_keys.iter() {
865 if account_locks.is_locked_write(k) {
866 debug!("Read-only account in use: {:?}", k);
867 return Err(TransactionError::AccountInUse);
868 }
869 }
870
871 for k in writable_keys {
872 account_locks.write_locks.insert(*k);
873 }
874
875 for k in readonly_keys {
876 if !account_locks.lock_readonly(k) {
877 account_locks.insert_new_readonly(k);
878 }
879 }
880
881 Ok(())
882 }
883
884 fn unlock_account(
885 &self,
886 account_locks: &mut AccountLocks,
887 writable_keys: Vec<&Pubkey>,
888 readonly_keys: Vec<&Pubkey>,
889 ) {
890 for k in writable_keys {
891 account_locks.unlock_write(k);
892 }
893 for k in readonly_keys {
894 account_locks.unlock_readonly(k);
895 }
896 }
897
898 pub fn bank_hash_at(&self, slot: Slot) -> Hash {
899 self.bank_hash_info_at(slot).hash
900 }
901
902 pub fn bank_hash_info_at(&self, slot: Slot) -> BankHashInfo {
903 let delta_hash = self.accounts_db.get_accounts_delta_hash(slot);
904 let bank_hashes = self.accounts_db.bank_hashes.read().unwrap();
905 let mut hash_info = bank_hashes
906 .get(&slot)
907 .expect("No bank hash was found for this bank, that should not be possible")
908 .clone();
909 hash_info.hash = delta_hash;
910 hash_info
911 }
912
913 #[must_use]
916 #[allow(clippy::needless_collect)]
917 pub fn lock_accounts<'a>(
918 &self,
919 txs: impl Iterator<Item = &'a SanitizedTransaction>,
920 demote_program_write_locks: bool,
921 ) -> Vec<Result<()>> {
922 let keys: Vec<_> = txs
923 .map(|tx| tx.get_account_locks(demote_program_write_locks))
924 .collect();
925 let mut account_locks = &mut self.account_locks.lock().unwrap();
926 keys.into_iter()
927 .map(|keys| self.lock_account(&mut account_locks, keys.writable, keys.readonly))
928 .collect()
929 }
930
931 #[allow(clippy::needless_collect)]
933 pub fn unlock_accounts<'a>(
934 &self,
935 txs: impl Iterator<Item = &'a SanitizedTransaction>,
936 results: &[Result<()>],
937 demote_program_write_locks: bool,
938 ) {
939 let keys: Vec<_> = txs
940 .zip(results)
941 .filter_map(|(tx, res)| match res {
942 Err(TransactionError::AccountInUse) => None,
943 Err(TransactionError::SanitizeFailure) => None,
944 Err(TransactionError::AccountLoadedTwice) => None,
945 _ => Some(tx.get_account_locks(demote_program_write_locks)),
946 })
947 .collect();
948 let mut account_locks = self.account_locks.lock().unwrap();
949 debug!("bank unlock accounts");
950 keys.into_iter().for_each(|keys| {
951 self.unlock_account(&mut account_locks, keys.writable, keys.readonly);
952 });
953 }
954
955 #[allow(clippy::too_many_arguments)]
958 pub fn store_cached<'a>(
959 &self,
960 slot: Slot,
961 txs: &'a [SanitizedTransaction],
962 res: &'a [TransactionExecutionResult],
963 loaded: &'a mut [TransactionLoadResult],
964 rent_collector: &RentCollector,
965 last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
966 rent_for_sysvars: bool,
967 merge_nonce_error_into_system_error: bool,
968 demote_program_write_locks: bool,
969 ) {
970 let accounts_to_store = self.collect_accounts_to_store(
971 txs,
972 res,
973 loaded,
974 rent_collector,
975 last_blockhash_with_fee_calculator,
976 rent_for_sysvars,
977 merge_nonce_error_into_system_error,
978 demote_program_write_locks,
979 );
980 self.accounts_db.store_cached(slot, &accounts_to_store);
981 }
982
983 pub fn purge_slot(&self, slot: Slot, bank_id: BankId, is_from_abs: bool) {
987 self.accounts_db.purge_slot(slot, bank_id, is_from_abs);
988 }
989
990 pub fn add_root(&self, slot: Slot) {
992 self.accounts_db.add_root(slot)
993 }
994
995 fn collect_accounts_to_store<'a>(
996 &self,
997 txs: &'a [SanitizedTransaction],
998 res: &'a [TransactionExecutionResult],
999 loaded: &'a mut [TransactionLoadResult],
1000 rent_collector: &RentCollector,
1001 last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
1002 rent_for_sysvars: bool,
1003 merge_nonce_error_into_system_error: bool,
1004 demote_program_write_locks: bool,
1005 ) -> Vec<(&'a Pubkey, &'a AccountSharedData)> {
1006 let mut accounts = Vec::with_capacity(loaded.len());
1007 for (i, ((raccs, _nonce_rollback), tx)) in loaded.iter_mut().zip(txs).enumerate() {
1008 if raccs.is_err() {
1009 continue;
1010 }
1011 let (res, nonce_rollback) = &res[i];
1012 let maybe_nonce_rollback = match (res, nonce_rollback) {
1013 (Ok(_), Some(nonce_rollback)) => {
1014 let pubkey = nonce_rollback.nonce_address();
1015 let acc = nonce_rollback.nonce_account();
1016 let maybe_fee_account = nonce_rollback.fee_account();
1017 Some((pubkey, acc, maybe_fee_account, true))
1018 }
1019 (Err(TransactionError::InstructionError(index, _)), Some(nonce_rollback)) => {
1020 let nonce_marker_ix_failed = if merge_nonce_error_into_system_error {
1021 *index == NONCED_TX_MARKER_IX_INDEX
1023 } else {
1024 false
1025 };
1026 let pubkey = nonce_rollback.nonce_address();
1027 let acc = nonce_rollback.nonce_account();
1028 let maybe_fee_account = nonce_rollback.fee_account();
1029 Some((pubkey, acc, maybe_fee_account, !nonce_marker_ix_failed))
1030 }
1031 (Ok(_), _nonce_rollback) => None,
1032 (Err(_), _nonce_rollback) => continue,
1033 };
1034
1035 let message = tx.message();
1036 let loaded_transaction = raccs.as_mut().unwrap();
1037 let mut fee_payer_index = None;
1038 for (i, (key, account)) in (0..message.account_keys_len())
1039 .zip(loaded_transaction.accounts.iter_mut())
1040 .filter(|(i, _account)| message.is_non_loader_key(*i))
1041 {
1042 let is_nonce_account = prepare_if_nonce_account(
1043 account,
1044 key,
1045 res,
1046 maybe_nonce_rollback,
1047 last_blockhash_with_fee_calculator,
1048 );
1049 if fee_payer_index.is_none() {
1050 fee_payer_index = Some(i);
1051 }
1052 let is_fee_payer = Some(i) == fee_payer_index;
1053 if message.is_writable(i, demote_program_write_locks)
1054 && (res.is_ok()
1055 || (maybe_nonce_rollback.is_some() && (is_nonce_account || is_fee_payer)))
1056 {
1057 if res.is_err() {
1058 match (is_nonce_account, is_fee_payer, maybe_nonce_rollback) {
1059 (true, true, Some((_, _, None, _))) => (),
1061 (true, false, Some((_, _, Some(_), _))) => (),
1063 (false, true, Some((_, _, Some(fee_payer_account), _))) => {
1065 *account = fee_payer_account.clone();
1066 }
1067 _ => panic!("unexpected nonce_rollback condition"),
1068 }
1069 }
1070 if account.rent_epoch() == INITIAL_RENT_EPOCH {
1071 let rent = rent_collector.collect_from_created_account(
1072 key,
1073 account,
1074 rent_for_sysvars,
1075 );
1076 loaded_transaction.rent += rent;
1077 loaded_transaction
1078 .rent_debits
1079 .push(key, rent, account.carats());
1080 }
1081 accounts.push((&*key, &*account));
1082 }
1083 }
1084 }
1085 accounts
1086 }
1087}
1088
1089pub fn prepare_if_nonce_account(
1090 account: &mut AccountSharedData,
1091 account_pubkey: &Pubkey,
1092 tx_result: &Result<()>,
1093 maybe_nonce_rollback: Option<(
1094 &Pubkey,
1095 &AccountSharedData,
1096 Option<&AccountSharedData>,
1097 bool,
1098 )>,
1099 last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
1100) -> bool {
1101 if let Some((nonce_key, nonce_acc, _maybe_fee_account, advance_blockhash)) =
1102 maybe_nonce_rollback
1103 {
1104 if account_pubkey == nonce_key {
1105 if tx_result.is_err() {
1106 *account = nonce_acc.clone();
1109 }
1110
1111 if advance_blockhash {
1112 let state = StateMut::<nonce::state::Versions>::state(nonce_acc)
1117 .unwrap()
1118 .convert_to_current();
1119 if let nonce::State::Initialized(ref data) = state {
1120 let new_data = nonce::state::Versions::new_current(nonce::State::Initialized(
1121 nonce::state::Data {
1122 blockhash: last_blockhash_with_fee_calculator.0,
1123 fee_calculator: last_blockhash_with_fee_calculator.1.clone(),
1124 ..data.clone()
1125 },
1126 ));
1127 account.set_state(&new_data).unwrap();
1128 }
1129 }
1130 return true;
1131 }
1132 }
1133 false
1134}
1135
1136fn is_upgradeable_loader_present(message: &SanitizedMessage) -> bool {
1137 message
1138 .account_keys_iter()
1139 .any(|&key| key == bpf_loader_upgradeable::id())
1140}
1141
1142pub fn create_test_accounts(
1143 accounts: &Accounts,
1144 pubkeys: &mut Vec<Pubkey>,
1145 num: usize,
1146 slot: Slot,
1147) {
1148 for t in 0..num {
1149 let pubkey = gemachain_sdk::pubkey::new_rand();
1150 let account =
1151 AccountSharedData::new((t + 1) as u64, 0, AccountSharedData::default().owner());
1152 accounts.store_slow_uncached(slot, &pubkey, &account);
1153 pubkeys.push(pubkey);
1154 }
1155}
1156
1157pub fn update_accounts_bench(accounts: &Accounts, pubkeys: &[Pubkey], slot: u64) {
1160 for pubkey in pubkeys {
1161 let amount = thread_rng().gen_range(0, 10);
1162 let account = AccountSharedData::new(amount, 0, AccountSharedData::default().owner());
1163 accounts.store_slow_uncached(slot, pubkey, &account);
1164 }
1165}
1166
1167#[cfg(test)]
1168mod tests {
1169 use super::*;
1170 use crate::rent_collector::RentCollector;
1171 use gemachain_sdk::{
1172 account::{AccountSharedData, WritableAccount},
1173 epoch_schedule::EpochSchedule,
1174 fee_calculator::FeeCalculator,
1175 genesis_config::ClusterType,
1176 hash::Hash,
1177 instruction::{CompiledInstruction, InstructionError},
1178 message::Message,
1179 nonce, nonce_account,
1180 rent::Rent,
1181 signature::{keypair_from_seed, signers::Signers, Keypair, Signer},
1182 system_instruction, system_program,
1183 transaction::Transaction,
1184 };
1185 use std::{
1186 convert::TryFrom,
1187 sync::atomic::{AtomicBool, AtomicU64, Ordering},
1188 {thread, time},
1189 };
1190
1191 fn new_sanitized_tx<T: Signers>(
1192 from_keypairs: &T,
1193 message: Message,
1194 recent_blockhash: Hash,
1195 ) -> SanitizedTransaction {
1196 SanitizedTransaction::try_from(Transaction::new(from_keypairs, message, recent_blockhash))
1197 .unwrap()
1198 }
1199
1200 fn load_accounts_with_fee_and_rent(
1201 tx: Transaction,
1202 ka: &[(Pubkey, AccountSharedData)],
1203 fee_calculator: &FeeCalculator,
1204 rent_collector: &RentCollector,
1205 error_counters: &mut ErrorCounters,
1206 ) -> Vec<TransactionLoadResult> {
1207 let mut hash_queue = BlockhashQueue::new(100);
1208 hash_queue.register_hash(&tx.message().recent_blockhash, fee_calculator);
1209 let accounts = Accounts::new_with_config_for_tests(
1210 Vec::new(),
1211 &ClusterType::Development,
1212 AccountSecondaryIndexes::default(),
1213 false,
1214 AccountShrinkThreshold::default(),
1215 );
1216 for ka in ka.iter() {
1217 accounts.store_slow_uncached(0, &ka.0, &ka.1);
1218 }
1219
1220 let ancestors = vec![(0, 0)].into_iter().collect();
1221 let sanitized_tx = SanitizedTransaction::try_from(tx).unwrap();
1222 accounts.load_accounts(
1223 &ancestors,
1224 &[sanitized_tx],
1225 vec![(Ok(()), None)],
1226 &hash_queue,
1227 error_counters,
1228 rent_collector,
1229 &FeatureSet::all_enabled(),
1230 )
1231 }
1232
1233 fn load_accounts_with_fee(
1234 tx: Transaction,
1235 ka: &[(Pubkey, AccountSharedData)],
1236 fee_calculator: &FeeCalculator,
1237 error_counters: &mut ErrorCounters,
1238 ) -> Vec<TransactionLoadResult> {
1239 let rent_collector = RentCollector::default();
1240 load_accounts_with_fee_and_rent(tx, ka, fee_calculator, &rent_collector, error_counters)
1241 }
1242
1243 fn load_accounts(
1244 tx: Transaction,
1245 ka: &[(Pubkey, AccountSharedData)],
1246 error_counters: &mut ErrorCounters,
1247 ) -> Vec<TransactionLoadResult> {
1248 let fee_calculator = FeeCalculator::default();
1249 load_accounts_with_fee(tx, ka, &fee_calculator, error_counters)
1250 }
1251
1252 #[test]
1253 fn test_hold_range_in_memory() {
1254 let accts = Accounts::default_for_tests();
1255 let range = Pubkey::new(&[0; 32])..=Pubkey::new(&[0xff; 32]);
1256 accts.hold_range_in_memory(&range, true);
1257 accts.hold_range_in_memory(&range, false);
1258 accts.hold_range_in_memory(&range, true);
1259 accts.hold_range_in_memory(&range, true);
1260 accts.hold_range_in_memory(&range, false);
1261 accts.hold_range_in_memory(&range, false);
1262 }
1263
1264 #[test]
1265 fn test_hold_range_in_memory2() {
1266 let accts = Accounts::default_for_tests();
1267 let range = Pubkey::new(&[0; 32])..=Pubkey::new(&[0xff; 32]);
1268 let idx = &accts.accounts_db.accounts_index;
1269 let bins = idx.account_maps.len();
1270 let bins_2 = bins * 2;
1272 let binner = crate::pubkey_bins::PubkeyBinCalculator16::new(bins_2);
1273 let range2 =
1274 binner.lowest_pubkey_from_bin(0, bins_2)..binner.lowest_pubkey_from_bin(1, bins_2);
1275 let range2_inclusive = range2.start..=range2.end;
1276 assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.start));
1277 assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.end));
1278 accts.hold_range_in_memory(&range, true);
1279 idx.account_maps.iter().enumerate().for_each(|(_bin, map)| {
1280 let map = map.read().unwrap();
1281 assert_eq!(
1282 map.cache_ranges_held.read().unwrap().to_vec(),
1283 vec![Some(range.clone())]
1284 );
1285 });
1286 accts.hold_range_in_memory(&range2, true);
1287 idx.account_maps.iter().enumerate().for_each(|(bin, map)| {
1288 let map = map.read().unwrap();
1289 let expected = if bin == 0 {
1290 vec![Some(range.clone()), Some(range2_inclusive.clone())]
1291 } else {
1292 vec![Some(range.clone())]
1293 };
1294 assert_eq!(
1295 map.cache_ranges_held.read().unwrap().to_vec(),
1296 expected,
1297 "bin: {}",
1298 bin
1299 );
1300 });
1301 accts.hold_range_in_memory(&range, false);
1302 accts.hold_range_in_memory(&range2, false);
1303 }
1304
1305 #[test]
1306 fn test_load_accounts_no_account_0_exists() {
1307 let accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1308 let mut error_counters = ErrorCounters::default();
1309
1310 let keypair = Keypair::new();
1311
1312 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1313 let tx = Transaction::new_with_compiled_instructions(
1314 &[&keypair],
1315 &[],
1316 Hash::default(),
1317 vec![native_loader::id()],
1318 instructions,
1319 );
1320
1321 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1322
1323 assert_eq!(error_counters.account_not_found, 1);
1324 assert_eq!(loaded_accounts.len(), 1);
1325 assert_eq!(
1326 loaded_accounts[0],
1327 (Err(TransactionError::AccountNotFound), None,),
1328 );
1329 }
1330
1331 #[test]
1332 fn test_load_accounts_unknown_program_id() {
1333 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1334 let mut error_counters = ErrorCounters::default();
1335
1336 let keypair = Keypair::new();
1337 let key0 = keypair.pubkey();
1338 let key1 = Pubkey::new(&[5u8; 32]);
1339
1340 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1341 accounts.push((key0, account));
1342
1343 let account = AccountSharedData::new(2, 1, &Pubkey::default());
1344 accounts.push((key1, account));
1345
1346 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1347 let tx = Transaction::new_with_compiled_instructions(
1348 &[&keypair],
1349 &[],
1350 Hash::default(),
1351 vec![Pubkey::default()],
1352 instructions,
1353 );
1354
1355 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1356
1357 assert_eq!(error_counters.account_not_found, 1);
1358 assert_eq!(loaded_accounts.len(), 1);
1359 assert_eq!(
1360 loaded_accounts[0],
1361 (Err(TransactionError::ProgramAccountNotFound), None,)
1362 );
1363 }
1364
1365 #[test]
1366 fn test_load_accounts_insufficient_funds() {
1367 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1368 let mut error_counters = ErrorCounters::default();
1369
1370 let keypair = Keypair::new();
1371 let key0 = keypair.pubkey();
1372
1373 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1374 accounts.push((key0, account));
1375
1376 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1377 let tx = Transaction::new_with_compiled_instructions(
1378 &[&keypair],
1379 &[],
1380 Hash::default(),
1381 vec![native_loader::id()],
1382 instructions,
1383 );
1384
1385 let fee_calculator = FeeCalculator::new(10);
1386 #[allow(deprecated)]
1387 let fee = fee_calculator.calculate_fee(tx.message());
1388 assert_eq!(fee, 10);
1389
1390 let loaded_accounts =
1391 load_accounts_with_fee(tx, &accounts, &fee_calculator, &mut error_counters);
1392
1393 assert_eq!(error_counters.insufficient_funds, 1);
1394 assert_eq!(loaded_accounts.len(), 1);
1395 assert_eq!(
1396 loaded_accounts[0].clone(),
1397 (Err(TransactionError::InsufficientFundsForFee), None,),
1398 );
1399 }
1400
1401 #[test]
1402 fn test_load_accounts_invalid_account_for_fee() {
1403 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1404 let mut error_counters = ErrorCounters::default();
1405
1406 let keypair = Keypair::new();
1407 let key0 = keypair.pubkey();
1408
1409 let account = AccountSharedData::new(1, 1, &gemachain_sdk::pubkey::new_rand()); accounts.push((key0, account));
1411
1412 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1413 let tx = Transaction::new_with_compiled_instructions(
1414 &[&keypair],
1415 &[],
1416 Hash::default(),
1417 vec![native_loader::id()],
1418 instructions,
1419 );
1420
1421 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1422
1423 assert_eq!(error_counters.invalid_account_for_fee, 1);
1424 assert_eq!(loaded_accounts.len(), 1);
1425 assert_eq!(
1426 loaded_accounts[0],
1427 (Err(TransactionError::InvalidAccountForFee), None,),
1428 );
1429 }
1430
1431 #[test]
1432 fn test_load_accounts_fee_payer_is_nonce() {
1433 let mut error_counters = ErrorCounters::default();
1434 let rent_collector = RentCollector::new(
1435 0,
1436 &EpochSchedule::default(),
1437 500_000.0,
1438 &Rent {
1439 carats_per_byte_year: 42,
1440 ..Rent::default()
1441 },
1442 );
1443 let min_balance = rent_collector.rent.minimum_balance(nonce::State::size());
1444 let fee_calculator = FeeCalculator::new(min_balance);
1445 let nonce = Keypair::new();
1446 let mut accounts = vec![(
1447 nonce.pubkey(),
1448 AccountSharedData::new_data(
1449 min_balance * 2,
1450 &nonce::state::Versions::new_current(nonce::State::Initialized(
1451 nonce::state::Data::default(),
1452 )),
1453 &system_program::id(),
1454 )
1455 .unwrap(),
1456 )];
1457 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1458 let tx = Transaction::new_with_compiled_instructions(
1459 &[&nonce],
1460 &[],
1461 Hash::default(),
1462 vec![native_loader::id()],
1463 instructions,
1464 );
1465
1466 let loaded_accounts = load_accounts_with_fee_and_rent(
1468 tx.clone(),
1469 &accounts,
1470 &fee_calculator,
1471 &rent_collector,
1472 &mut error_counters,
1473 );
1474 assert_eq!(loaded_accounts.len(), 1);
1475 let (load_res, _nonce_rollback) = &loaded_accounts[0];
1476 let loaded_transaction = load_res.as_ref().unwrap();
1477 assert_eq!(loaded_transaction.accounts[0].1.carats(), min_balance);
1478
1479 accounts[0].1.set_carats(min_balance);
1481 let loaded_accounts = load_accounts_with_fee_and_rent(
1482 tx.clone(),
1483 &accounts,
1484 &fee_calculator,
1485 &rent_collector,
1486 &mut error_counters,
1487 );
1488 assert_eq!(loaded_accounts.len(), 1);
1489 let (load_res, _nonce_rollback) = &loaded_accounts[0];
1490 assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
1491
1492 accounts[0].1.set_carats(3 * min_balance / 2);
1494 let loaded_accounts = load_accounts_with_fee_and_rent(
1495 tx,
1496 &accounts,
1497 &fee_calculator,
1498 &rent_collector,
1499 &mut error_counters,
1500 );
1501 assert_eq!(loaded_accounts.len(), 1);
1502 let (load_res, _nonce_rollback) = &loaded_accounts[0];
1503 assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
1504 }
1505
1506 #[test]
1507 fn test_load_accounts_no_loaders() {
1508 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1509 let mut error_counters = ErrorCounters::default();
1510
1511 let keypair = Keypair::new();
1512 let key0 = keypair.pubkey();
1513 let key1 = Pubkey::new(&[5u8; 32]);
1514
1515 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1516 account.set_rent_epoch(1);
1517 accounts.push((key0, account));
1518
1519 let mut account = AccountSharedData::new(2, 1, &Pubkey::default());
1520 account.set_rent_epoch(1);
1521 accounts.push((key1, account));
1522
1523 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1524 let tx = Transaction::new_with_compiled_instructions(
1525 &[&keypair],
1526 &[key1],
1527 Hash::default(),
1528 vec![native_loader::id()],
1529 instructions,
1530 );
1531
1532 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1533
1534 assert_eq!(error_counters.account_not_found, 0);
1535 assert_eq!(loaded_accounts.len(), 1);
1536 match &loaded_accounts[0] {
1537 (Ok(loaded_transaction), _nonce_rollback) => {
1538 assert_eq!(loaded_transaction.accounts.len(), 3);
1539 assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
1540 assert_eq!(loaded_transaction.program_indices.len(), 1);
1541 assert_eq!(loaded_transaction.program_indices[0].len(), 0);
1542 }
1543 (Err(e), _nonce_rollback) => Err(e).unwrap(),
1544 }
1545 }
1546
1547 #[test]
1548 fn test_load_accounts_max_call_depth() {
1549 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1550 let mut error_counters = ErrorCounters::default();
1551
1552 let keypair = Keypair::new();
1553 let key0 = keypair.pubkey();
1554 let key1 = Pubkey::new(&[5u8; 32]);
1555 let key2 = Pubkey::new(&[6u8; 32]);
1556 let key3 = Pubkey::new(&[7u8; 32]);
1557 let key4 = Pubkey::new(&[8u8; 32]);
1558 let key5 = Pubkey::new(&[9u8; 32]);
1559 let key6 = Pubkey::new(&[10u8; 32]);
1560
1561 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1562 accounts.push((key0, account));
1563
1564 let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1565 account.set_executable(true);
1566 account.set_owner(native_loader::id());
1567 accounts.push((key1, account));
1568
1569 let mut account = AccountSharedData::new(41, 1, &Pubkey::default());
1570 account.set_executable(true);
1571 account.set_owner(key1);
1572 accounts.push((key2, account));
1573
1574 let mut account = AccountSharedData::new(42, 1, &Pubkey::default());
1575 account.set_executable(true);
1576 account.set_owner(key2);
1577 accounts.push((key3, account));
1578
1579 let mut account = AccountSharedData::new(43, 1, &Pubkey::default());
1580 account.set_executable(true);
1581 account.set_owner(key3);
1582 accounts.push((key4, account));
1583
1584 let mut account = AccountSharedData::new(44, 1, &Pubkey::default());
1585 account.set_executable(true);
1586 account.set_owner(key4);
1587 accounts.push((key5, account));
1588
1589 let mut account = AccountSharedData::new(45, 1, &Pubkey::default());
1590 account.set_executable(true);
1591 account.set_owner(key5);
1592 accounts.push((key6, account));
1593
1594 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1595 let tx = Transaction::new_with_compiled_instructions(
1596 &[&keypair],
1597 &[],
1598 Hash::default(),
1599 vec![key6],
1600 instructions,
1601 );
1602
1603 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1604
1605 assert_eq!(error_counters.call_chain_too_deep, 1);
1606 assert_eq!(loaded_accounts.len(), 1);
1607 assert_eq!(
1608 loaded_accounts[0],
1609 (Err(TransactionError::CallChainTooDeep), None,)
1610 );
1611 }
1612
1613 #[test]
1614 fn test_load_accounts_bad_owner() {
1615 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1616 let mut error_counters = ErrorCounters::default();
1617
1618 let keypair = Keypair::new();
1619 let key0 = keypair.pubkey();
1620 let key1 = Pubkey::new(&[5u8; 32]);
1621
1622 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1623 accounts.push((key0, account));
1624
1625 let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1626 account.set_executable(true);
1627 accounts.push((key1, account));
1628
1629 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1630 let tx = Transaction::new_with_compiled_instructions(
1631 &[&keypair],
1632 &[],
1633 Hash::default(),
1634 vec![key1],
1635 instructions,
1636 );
1637
1638 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1639
1640 assert_eq!(error_counters.account_not_found, 1);
1641 assert_eq!(loaded_accounts.len(), 1);
1642 assert_eq!(
1643 loaded_accounts[0],
1644 (Err(TransactionError::ProgramAccountNotFound), None,)
1645 );
1646 }
1647
1648 #[test]
1649 fn test_load_accounts_not_executable() {
1650 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1651 let mut error_counters = ErrorCounters::default();
1652
1653 let keypair = Keypair::new();
1654 let key0 = keypair.pubkey();
1655 let key1 = Pubkey::new(&[5u8; 32]);
1656
1657 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1658 accounts.push((key0, account));
1659
1660 let account = AccountSharedData::new(40, 1, &native_loader::id());
1661 accounts.push((key1, account));
1662
1663 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1664 let tx = Transaction::new_with_compiled_instructions(
1665 &[&keypair],
1666 &[],
1667 Hash::default(),
1668 vec![key1],
1669 instructions,
1670 );
1671
1672 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1673
1674 assert_eq!(error_counters.invalid_program_for_execution, 1);
1675 assert_eq!(loaded_accounts.len(), 1);
1676 assert_eq!(
1677 loaded_accounts[0],
1678 (Err(TransactionError::InvalidProgramForExecution), None,)
1679 );
1680 }
1681
1682 #[test]
1683 fn test_load_accounts_multiple_loaders() {
1684 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1685 let mut error_counters = ErrorCounters::default();
1686
1687 let keypair = Keypair::new();
1688 let key0 = keypair.pubkey();
1689 let key1 = Pubkey::new(&[5u8; 32]);
1690 let key2 = Pubkey::new(&[6u8; 32]);
1691
1692 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1693 account.set_rent_epoch(1);
1694 accounts.push((key0, account));
1695
1696 let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1697 account.set_executable(true);
1698 account.set_rent_epoch(1);
1699 account.set_owner(native_loader::id());
1700 accounts.push((key1, account));
1701
1702 let mut account = AccountSharedData::new(41, 1, &Pubkey::default());
1703 account.set_executable(true);
1704 account.set_rent_epoch(1);
1705 account.set_owner(key1);
1706 accounts.push((key2, account));
1707
1708 let instructions = vec![
1709 CompiledInstruction::new(1, &(), vec![0]),
1710 CompiledInstruction::new(2, &(), vec![0]),
1711 ];
1712 let tx = Transaction::new_with_compiled_instructions(
1713 &[&keypair],
1714 &[],
1715 Hash::default(),
1716 vec![key1, key2],
1717 instructions,
1718 );
1719
1720 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1721
1722 assert_eq!(error_counters.account_not_found, 0);
1723 assert_eq!(loaded_accounts.len(), 1);
1724 match &loaded_accounts[0] {
1725 (Ok(loaded_transaction), _nonce_rollback) => {
1726 assert_eq!(loaded_transaction.accounts.len(), 6);
1727 assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
1728 assert_eq!(loaded_transaction.program_indices.len(), 2);
1729 assert_eq!(loaded_transaction.program_indices[0].len(), 1);
1730 assert_eq!(loaded_transaction.program_indices[1].len(), 2);
1731 for program_indices in loaded_transaction.program_indices.iter() {
1732 for (i, program_index) in program_indices.iter().enumerate() {
1733 assert_eq!(
1735 loaded_transaction.accounts[*program_index].0,
1736 accounts[i + 1].0
1737 );
1738 assert_eq!(
1739 loaded_transaction.accounts[*program_index].1,
1740 accounts[i + 1].1
1741 );
1742 }
1743 }
1744 }
1745 (Err(e), _nonce_rollback) => Err(e).unwrap(),
1746 }
1747 }
1748
1749 #[test]
1750 fn test_load_by_program_slot() {
1751 let accounts = Accounts::new_with_config_for_tests(
1752 Vec::new(),
1753 &ClusterType::Development,
1754 AccountSecondaryIndexes::default(),
1755 false,
1756 AccountShrinkThreshold::default(),
1757 );
1758
1759 let pubkey0 = gemachain_sdk::pubkey::new_rand();
1761 let account0 = AccountSharedData::new(1, 0, &Pubkey::new(&[2; 32]));
1762 accounts.store_slow_uncached(0, &pubkey0, &account0);
1763 let pubkey1 = gemachain_sdk::pubkey::new_rand();
1764 let account1 = AccountSharedData::new(1, 0, &Pubkey::new(&[2; 32]));
1765 accounts.store_slow_uncached(0, &pubkey1, &account1);
1766 let pubkey2 = gemachain_sdk::pubkey::new_rand();
1767 let account2 = AccountSharedData::new(1, 0, &Pubkey::new(&[3; 32]));
1768 accounts.store_slow_uncached(0, &pubkey2, &account2);
1769
1770 let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::new(&[2; 32])));
1771 assert_eq!(loaded.len(), 2);
1772 let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::new(&[3; 32])));
1773 assert_eq!(loaded, vec![(pubkey2, account2)]);
1774 let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::new(&[4; 32])));
1775 assert_eq!(loaded, vec![]);
1776 }
1777
1778 #[test]
1779 fn test_load_accounts_executable_with_write_lock() {
1780 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1781 let mut error_counters = ErrorCounters::default();
1782
1783 let keypair = Keypair::new();
1784 let key0 = keypair.pubkey();
1785 let key1 = Pubkey::new(&[5u8; 32]);
1786 let key2 = Pubkey::new(&[6u8; 32]);
1787
1788 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1789 account.set_rent_epoch(1);
1790 accounts.push((key0, account));
1791
1792 let mut account = AccountSharedData::new(40, 1, &native_loader::id());
1793 account.set_executable(true);
1794 account.set_rent_epoch(1);
1795 accounts.push((key1, account));
1796
1797 let mut account = AccountSharedData::new(40, 1, &native_loader::id());
1798 account.set_executable(true);
1799 account.set_rent_epoch(1);
1800 accounts.push((key2, account));
1801
1802 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1803 let mut message = Message::new_with_compiled_instructions(
1804 1,
1805 0,
1806 1, vec![key0, key1, key2],
1808 Hash::default(),
1809 instructions,
1810 );
1811 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1812 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1813
1814 assert_eq!(error_counters.invalid_writable_account, 1);
1815 assert_eq!(loaded_accounts.len(), 1);
1816 assert_eq!(
1817 loaded_accounts[0],
1818 (Err(TransactionError::InvalidWritableAccount), None)
1819 );
1820
1821 message.account_keys = vec![key0, key1, key2]; message.header.num_readonly_unsigned_accounts = 2; let tx = Transaction::new(&[&keypair], message, Hash::default());
1825 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1826
1827 assert_eq!(error_counters.invalid_writable_account, 1);
1828 assert_eq!(loaded_accounts.len(), 1);
1829 let result = loaded_accounts[0].0.as_ref().unwrap();
1830 assert_eq!(result.accounts[..2], accounts[..2]);
1831 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[2]);
1832 }
1833
1834 #[test]
1835 fn test_load_accounts_upgradeable_with_write_lock() {
1836 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1837 let mut error_counters = ErrorCounters::default();
1838
1839 let keypair = Keypair::new();
1840 let key0 = keypair.pubkey();
1841 let key1 = Pubkey::new(&[5u8; 32]);
1842 let key2 = Pubkey::new(&[6u8; 32]);
1843 let programdata_key1 = Pubkey::new(&[7u8; 32]);
1844 let programdata_key2 = Pubkey::new(&[8u8; 32]);
1845
1846 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1847 account.set_rent_epoch(1);
1848 accounts.push((key0, account));
1849
1850 let program_data = UpgradeableLoaderState::ProgramData {
1851 slot: 42,
1852 upgrade_authority_address: None,
1853 };
1854
1855 let program = UpgradeableLoaderState::Program {
1856 programdata_address: programdata_key1,
1857 };
1858 let mut account =
1859 AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap();
1860 account.set_executable(true);
1861 account.set_rent_epoch(1);
1862 accounts.push((key1, account));
1863 let mut account =
1864 AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
1865 account.set_rent_epoch(1);
1866 accounts.push((programdata_key1, account));
1867
1868 let program = UpgradeableLoaderState::Program {
1869 programdata_address: programdata_key2,
1870 };
1871 let mut account =
1872 AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap();
1873 account.set_executable(true);
1874 account.set_rent_epoch(1);
1875 accounts.push((key2, account));
1876 let mut account =
1877 AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
1878 account.set_rent_epoch(1);
1879 accounts.push((programdata_key2, account));
1880
1881 let mut account = AccountSharedData::new(40, 1, &native_loader::id()); account.set_executable(true);
1883 account.set_rent_epoch(1);
1884 accounts.push((bpf_loader_upgradeable::id(), account));
1885
1886 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1887 let mut message = Message::new_with_compiled_instructions(
1888 1,
1889 0,
1890 1, vec![key0, key1, key2],
1892 Hash::default(),
1893 instructions,
1894 );
1895 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1896 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1897
1898 assert_eq!(error_counters.invalid_writable_account, 1);
1899 assert_eq!(loaded_accounts.len(), 1);
1900 assert_eq!(
1901 loaded_accounts[0],
1902 (Err(TransactionError::InvalidWritableAccount), None)
1903 );
1904
1905 message.account_keys = vec![key0, key1, bpf_loader_upgradeable::id()];
1907 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1908 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1909
1910 assert_eq!(error_counters.invalid_writable_account, 1);
1911 assert_eq!(loaded_accounts.len(), 1);
1912 let result = loaded_accounts[0].0.as_ref().unwrap();
1913 assert_eq!(result.accounts[..2], accounts[..2]);
1914 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[5]);
1915
1916 message.account_keys = vec![key0, key1, key2]; message.header.num_readonly_unsigned_accounts = 2; let tx = Transaction::new(&[&keypair], message, Hash::default());
1920 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1921
1922 assert_eq!(error_counters.invalid_writable_account, 1);
1923 assert_eq!(loaded_accounts.len(), 1);
1924 let result = loaded_accounts[0].0.as_ref().unwrap();
1925 assert_eq!(result.accounts[..2], accounts[..2]);
1926 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[5]);
1927 assert_eq!(result.accounts[result.program_indices[0][1]], accounts[3]);
1928 assert_eq!(result.accounts[result.program_indices[0][2]], accounts[4]);
1929 }
1930
1931 #[test]
1932 fn test_load_accounts_programdata_with_write_lock() {
1933 let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1934 let mut error_counters = ErrorCounters::default();
1935
1936 let keypair = Keypair::new();
1937 let key0 = keypair.pubkey();
1938 let key1 = Pubkey::new(&[5u8; 32]);
1939 let key2 = Pubkey::new(&[6u8; 32]);
1940
1941 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1942 account.set_rent_epoch(1);
1943 accounts.push((key0, account));
1944
1945 let program_data = UpgradeableLoaderState::ProgramData {
1946 slot: 42,
1947 upgrade_authority_address: None,
1948 };
1949 let mut account =
1950 AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
1951 account.set_rent_epoch(1);
1952 accounts.push((key1, account));
1953
1954 let mut account = AccountSharedData::new(40, 1, &native_loader::id());
1955 account.set_executable(true);
1956 account.set_rent_epoch(1);
1957 accounts.push((key2, account));
1958
1959 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1960 let mut message = Message::new_with_compiled_instructions(
1961 1,
1962 0,
1963 1, vec![key0, key1, key2],
1965 Hash::default(),
1966 instructions,
1967 );
1968 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1969 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1970
1971 assert_eq!(error_counters.invalid_writable_account, 1);
1972 assert_eq!(loaded_accounts.len(), 1);
1973 assert_eq!(
1974 loaded_accounts[0],
1975 (Err(TransactionError::InvalidWritableAccount), None)
1976 );
1977
1978 let mut account = AccountSharedData::new(40, 1, &native_loader::id()); account.set_executable(true);
1981 account.set_rent_epoch(1);
1982 let accounts_with_upgradeable_loader = vec![
1983 accounts[0].clone(),
1984 accounts[1].clone(),
1985 (bpf_loader_upgradeable::id(), account),
1986 ];
1987 message.account_keys = vec![key0, key1, bpf_loader_upgradeable::id()];
1988 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1989 let loaded_accounts =
1990 load_accounts(tx, &accounts_with_upgradeable_loader, &mut error_counters);
1991
1992 assert_eq!(error_counters.invalid_writable_account, 1);
1993 assert_eq!(loaded_accounts.len(), 1);
1994 let result = loaded_accounts[0].0.as_ref().unwrap();
1995 assert_eq!(result.accounts[..2], accounts_with_upgradeable_loader[..2]);
1996 assert_eq!(
1997 result.accounts[result.program_indices[0][0]],
1998 accounts_with_upgradeable_loader[2]
1999 );
2000
2001 message.account_keys = vec![key0, key1, key2]; message.header.num_readonly_unsigned_accounts = 2; let tx = Transaction::new(&[&keypair], message, Hash::default());
2005 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2006
2007 assert_eq!(error_counters.invalid_writable_account, 1);
2008 assert_eq!(loaded_accounts.len(), 1);
2009 let result = loaded_accounts[0].0.as_ref().unwrap();
2010 assert_eq!(result.accounts[..2], accounts[..2]);
2011 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[2]);
2012 }
2013
2014 #[test]
2015 fn test_accounts_account_not_found() {
2016 let accounts = Accounts::new_with_config_for_tests(
2017 Vec::new(),
2018 &ClusterType::Development,
2019 AccountSecondaryIndexes::default(),
2020 false,
2021 AccountShrinkThreshold::default(),
2022 );
2023 let mut error_counters = ErrorCounters::default();
2024 let ancestors = vec![(0, 0)].into_iter().collect();
2025
2026 let keypair = Keypair::new();
2027 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
2028 account.set_executable(true);
2029 accounts.store_slow_uncached(0, &keypair.pubkey(), &account);
2030
2031 assert_eq!(
2032 accounts.load_executable_accounts(
2033 &ancestors,
2034 &mut vec![(keypair.pubkey(), account)],
2035 0,
2036 &mut error_counters,
2037 ),
2038 Err(TransactionError::ProgramAccountNotFound)
2039 );
2040 assert_eq!(error_counters.account_not_found, 1);
2041 }
2042
2043 #[test]
2044 #[should_panic]
2045 fn test_accounts_empty_bank_hash() {
2046 let accounts = Accounts::new_with_config_for_tests(
2047 Vec::new(),
2048 &ClusterType::Development,
2049 AccountSecondaryIndexes::default(),
2050 false,
2051 AccountShrinkThreshold::default(),
2052 );
2053 accounts.bank_hash_at(1);
2054 }
2055
2056 #[test]
2057 fn test_accounts_locks() {
2058 let keypair0 = Keypair::new();
2059 let keypair1 = Keypair::new();
2060 let keypair2 = Keypair::new();
2061 let keypair3 = Keypair::new();
2062
2063 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2064 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2065 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2066 let account3 = AccountSharedData::new(4, 0, &Pubkey::default());
2067
2068 let accounts = Accounts::new_with_config_for_tests(
2069 Vec::new(),
2070 &ClusterType::Development,
2071 AccountSecondaryIndexes::default(),
2072 false,
2073 AccountShrinkThreshold::default(),
2074 );
2075 accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2076 accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2077 accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2078 accounts.store_slow_uncached(0, &keypair3.pubkey(), &account3);
2079
2080 let demote_program_write_locks = true;
2081
2082 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2083 let message = Message::new_with_compiled_instructions(
2084 1,
2085 0,
2086 2,
2087 vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2088 Hash::default(),
2089 instructions,
2090 );
2091 let tx = new_sanitized_tx(&[&keypair0], message, Hash::default());
2092 let results0 = accounts.lock_accounts([tx.clone()].iter(), demote_program_write_locks);
2093
2094 assert!(results0[0].is_ok());
2095 assert_eq!(
2096 *accounts
2097 .account_locks
2098 .lock()
2099 .unwrap()
2100 .readonly_locks
2101 .get(&keypair1.pubkey())
2102 .unwrap(),
2103 1
2104 );
2105
2106 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2107 let message = Message::new_with_compiled_instructions(
2108 1,
2109 0,
2110 2,
2111 vec![keypair2.pubkey(), keypair1.pubkey(), native_loader::id()],
2112 Hash::default(),
2113 instructions,
2114 );
2115 let tx0 = new_sanitized_tx(&[&keypair2], message, Hash::default());
2116 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2117 let message = Message::new_with_compiled_instructions(
2118 1,
2119 0,
2120 2,
2121 vec![keypair1.pubkey(), keypair3.pubkey(), native_loader::id()],
2122 Hash::default(),
2123 instructions,
2124 );
2125 let tx1 = new_sanitized_tx(&[&keypair1], message, Hash::default());
2126 let txs = vec![tx0, tx1];
2127 let results1 = accounts.lock_accounts(txs.iter(), demote_program_write_locks);
2128
2129 assert!(results1[0].is_ok()); assert!(results1[1].is_err()); assert_eq!(
2132 *accounts
2133 .account_locks
2134 .lock()
2135 .unwrap()
2136 .readonly_locks
2137 .get(&keypair1.pubkey())
2138 .unwrap(),
2139 2
2140 );
2141
2142 accounts.unlock_accounts([tx].iter(), &results0, demote_program_write_locks);
2143 accounts.unlock_accounts(txs.iter(), &results1, demote_program_write_locks);
2144 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2145 let message = Message::new_with_compiled_instructions(
2146 1,
2147 0,
2148 2,
2149 vec![keypair1.pubkey(), keypair3.pubkey(), native_loader::id()],
2150 Hash::default(),
2151 instructions,
2152 );
2153 let tx = new_sanitized_tx(&[&keypair1], message, Hash::default());
2154 let results2 = accounts.lock_accounts([tx].iter(), demote_program_write_locks);
2155 assert!(results2[0].is_ok()); assert!(accounts
2159 .account_locks
2160 .lock()
2161 .unwrap()
2162 .readonly_locks
2163 .get(&keypair1.pubkey())
2164 .is_none());
2165 }
2166
2167 #[test]
2168 fn test_accounts_locks_multithreaded() {
2169 let counter = Arc::new(AtomicU64::new(0));
2170 let exit = Arc::new(AtomicBool::new(false));
2171
2172 let keypair0 = Keypair::new();
2173 let keypair1 = Keypair::new();
2174 let keypair2 = Keypair::new();
2175
2176 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2177 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2178 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2179
2180 let accounts = Accounts::new_with_config_for_tests(
2181 Vec::new(),
2182 &ClusterType::Development,
2183 AccountSecondaryIndexes::default(),
2184 false,
2185 AccountShrinkThreshold::default(),
2186 );
2187 accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2188 accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2189 accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2190
2191 let demote_program_write_locks = true;
2192
2193 let accounts_arc = Arc::new(accounts);
2194
2195 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2196 let readonly_message = Message::new_with_compiled_instructions(
2197 1,
2198 0,
2199 2,
2200 vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2201 Hash::default(),
2202 instructions,
2203 );
2204 let readonly_tx = new_sanitized_tx(&[&keypair0], readonly_message, Hash::default());
2205
2206 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2207 let writable_message = Message::new_with_compiled_instructions(
2208 1,
2209 0,
2210 2,
2211 vec![keypair1.pubkey(), keypair2.pubkey(), native_loader::id()],
2212 Hash::default(),
2213 instructions,
2214 );
2215 let writable_tx = new_sanitized_tx(&[&keypair1], writable_message, Hash::default());
2216
2217 let counter_clone = counter.clone();
2218 let accounts_clone = accounts_arc.clone();
2219 let exit_clone = exit.clone();
2220 thread::spawn(move || {
2221 let counter_clone = counter_clone.clone();
2222 let exit_clone = exit_clone.clone();
2223 loop {
2224 let txs = vec![writable_tx.clone()];
2225 let results = accounts_clone
2226 .clone()
2227 .lock_accounts(txs.iter(), demote_program_write_locks);
2228 for result in results.iter() {
2229 if result.is_ok() {
2230 counter_clone.clone().fetch_add(1, Ordering::SeqCst);
2231 }
2232 }
2233 accounts_clone.unlock_accounts(txs.iter(), &results, demote_program_write_locks);
2234 if exit_clone.clone().load(Ordering::Relaxed) {
2235 break;
2236 }
2237 }
2238 });
2239 let counter_clone = counter;
2240 for _ in 0..5 {
2241 let txs = vec![readonly_tx.clone()];
2242 let results = accounts_arc
2243 .clone()
2244 .lock_accounts(txs.iter(), demote_program_write_locks);
2245 if results[0].is_ok() {
2246 let counter_value = counter_clone.clone().load(Ordering::SeqCst);
2247 thread::sleep(time::Duration::from_millis(50));
2248 assert_eq!(counter_value, counter_clone.clone().load(Ordering::SeqCst));
2249 }
2250 accounts_arc.unlock_accounts(txs.iter(), &results, demote_program_write_locks);
2251 thread::sleep(time::Duration::from_millis(50));
2252 }
2253 exit.store(true, Ordering::Relaxed);
2254 }
2255
2256 #[test]
2257 fn test_demote_program_write_locks() {
2258 let keypair0 = Keypair::new();
2259 let keypair1 = Keypair::new();
2260 let keypair2 = Keypair::new();
2261 let keypair3 = Keypair::new();
2262
2263 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2264 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2265 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2266 let account3 = AccountSharedData::new(4, 0, &Pubkey::default());
2267
2268 let accounts = Accounts::new_with_config_for_tests(
2269 Vec::new(),
2270 &ClusterType::Development,
2271 AccountSecondaryIndexes::default(),
2272 false,
2273 AccountShrinkThreshold::default(),
2274 );
2275 accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2276 accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2277 accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2278 accounts.store_slow_uncached(0, &keypair3.pubkey(), &account3);
2279
2280 let demote_program_write_locks = true;
2281
2282 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2283 let message = Message::new_with_compiled_instructions(
2284 1,
2285 0,
2286 0, vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2288 Hash::default(),
2289 instructions,
2290 );
2291 let tx = new_sanitized_tx(&[&keypair0], message, Hash::default());
2292 let results0 = accounts.lock_accounts([tx].iter(), demote_program_write_locks);
2293
2294 assert!(results0[0].is_ok());
2295 assert_eq!(
2297 *accounts
2298 .account_locks
2299 .lock()
2300 .unwrap()
2301 .readonly_locks
2302 .get(&native_loader::id())
2303 .unwrap(),
2304 1
2305 );
2306 assert!(accounts
2308 .account_locks
2309 .lock()
2310 .unwrap()
2311 .write_locks
2312 .contains(&keypair0.pubkey()));
2313 assert!(accounts
2314 .account_locks
2315 .lock()
2316 .unwrap()
2317 .write_locks
2318 .contains(&keypair1.pubkey()));
2319 }
2320
2321 #[test]
2322 fn test_collect_accounts_to_store() {
2323 let keypair0 = Keypair::new();
2324 let keypair1 = Keypair::new();
2325 let pubkey = gemachain_sdk::pubkey::new_rand();
2326 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2327 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2328 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2329
2330 let rent_collector = RentCollector::default();
2331
2332 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2333 let message = Message::new_with_compiled_instructions(
2334 1,
2335 0,
2336 2,
2337 vec![keypair0.pubkey(), pubkey, native_loader::id()],
2338 Hash::default(),
2339 instructions,
2340 );
2341 let transaction_accounts0 = vec![
2342 (message.account_keys[0], account0),
2343 (message.account_keys[1], account2.clone()),
2344 ];
2345 let tx0 = new_sanitized_tx(&[&keypair0], message, Hash::default());
2346
2347 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2348 let message = Message::new_with_compiled_instructions(
2349 1,
2350 0,
2351 2,
2352 vec![keypair1.pubkey(), pubkey, native_loader::id()],
2353 Hash::default(),
2354 instructions,
2355 );
2356 let transaction_accounts1 = vec![
2357 (message.account_keys[0], account1),
2358 (message.account_keys[1], account2),
2359 ];
2360 let tx1 = new_sanitized_tx(&[&keypair1], message, Hash::default());
2361
2362 let loaded0 = (
2363 Ok(LoadedTransaction {
2364 accounts: transaction_accounts0,
2365 program_indices: vec![],
2366 rent: 0,
2367 rent_debits: RentDebits::default(),
2368 }),
2369 None,
2370 );
2371
2372 let loaded1 = (
2373 Ok(LoadedTransaction {
2374 accounts: transaction_accounts1,
2375 program_indices: vec![],
2376 rent: 0,
2377 rent_debits: RentDebits::default(),
2378 }),
2379 None,
2380 );
2381
2382 let mut loaded = vec![loaded0, loaded1];
2383
2384 let accounts = Accounts::new_with_config_for_tests(
2385 Vec::new(),
2386 &ClusterType::Development,
2387 AccountSecondaryIndexes::default(),
2388 false,
2389 AccountShrinkThreshold::default(),
2390 );
2391 {
2392 accounts
2393 .account_locks
2394 .lock()
2395 .unwrap()
2396 .insert_new_readonly(&pubkey);
2397 }
2398 let txs = vec![tx0, tx1];
2399 let programs = vec![(Ok(()), None), (Ok(()), None)];
2400 let collected_accounts = accounts.collect_accounts_to_store(
2401 &txs,
2402 &programs,
2403 loaded.as_mut_slice(),
2404 &rent_collector,
2405 &(Hash::default(), FeeCalculator::default()),
2406 true,
2407 true, true, );
2410 assert_eq!(collected_accounts.len(), 2);
2411 assert!(collected_accounts
2412 .iter()
2413 .any(|(pubkey, _account)| *pubkey == &keypair0.pubkey()));
2414 assert!(collected_accounts
2415 .iter()
2416 .any(|(pubkey, _account)| *pubkey == &keypair1.pubkey()));
2417
2418 assert_eq!(
2420 *accounts
2421 .account_locks
2422 .lock()
2423 .unwrap()
2424 .readonly_locks
2425 .get(&pubkey)
2426 .unwrap(),
2427 1
2428 );
2429 }
2430
2431 #[test]
2432 fn huge_clean() {
2433 gemachain_logger::setup();
2434 let accounts = Accounts::new_with_config_for_tests(
2435 Vec::new(),
2436 &ClusterType::Development,
2437 AccountSecondaryIndexes::default(),
2438 false,
2439 AccountShrinkThreshold::default(),
2440 );
2441 let mut old_pubkey = Pubkey::default();
2442 let zero_account = AccountSharedData::new(0, 0, AccountSharedData::default().owner());
2443 info!("storing..");
2444 for i in 0..2_000 {
2445 let pubkey = gemachain_sdk::pubkey::new_rand();
2446 let account =
2447 AccountSharedData::new((i + 1) as u64, 0, AccountSharedData::default().owner());
2448 accounts.store_slow_uncached(i, &pubkey, &account);
2449 accounts.store_slow_uncached(i, &old_pubkey, &zero_account);
2450 old_pubkey = pubkey;
2451 accounts.add_root(i);
2452 if i % 1_000 == 0 {
2453 info!(" store {}", i);
2454 }
2455 }
2456 info!("done..cleaning..");
2457 accounts.accounts_db.clean_accounts(None, false, None);
2458 }
2459
2460 fn load_accounts_no_store(accounts: &Accounts, tx: Transaction) -> Vec<TransactionLoadResult> {
2461 let tx = SanitizedTransaction::try_from(tx).unwrap();
2462 let rent_collector = RentCollector::default();
2463 let fee_calculator = FeeCalculator::new(10);
2464 let mut hash_queue = BlockhashQueue::new(100);
2465 hash_queue.register_hash(tx.message().recent_blockhash(), &fee_calculator);
2466
2467 let ancestors = vec![(0, 0)].into_iter().collect();
2468 let mut error_counters = ErrorCounters::default();
2469 accounts.load_accounts(
2470 &ancestors,
2471 &[tx],
2472 vec![(Ok(()), None)],
2473 &hash_queue,
2474 &mut error_counters,
2475 &rent_collector,
2476 &FeatureSet::all_enabled(),
2477 )
2478 }
2479
2480 #[test]
2481 fn test_instructions() {
2482 gemachain_logger::setup();
2483 let accounts = Accounts::new_with_config_for_tests(
2484 Vec::new(),
2485 &ClusterType::Development,
2486 AccountSecondaryIndexes::default(),
2487 false,
2488 AccountShrinkThreshold::default(),
2489 );
2490
2491 let instructions_key = gemachain_sdk::sysvar::instructions::id();
2492 let keypair = Keypair::new();
2493 let instructions = vec![CompiledInstruction::new(1, &(), vec![0, 1])];
2494 let tx = Transaction::new_with_compiled_instructions(
2495 &[&keypair],
2496 &[gemachain_sdk::pubkey::new_rand(), instructions_key],
2497 Hash::default(),
2498 vec![native_loader::id()],
2499 instructions,
2500 );
2501
2502 let loaded_accounts = load_accounts_no_store(&accounts, tx);
2503 assert_eq!(loaded_accounts.len(), 1);
2504 assert!(loaded_accounts[0].0.is_err());
2505 }
2506
2507 fn create_accounts_prepare_if_nonce_account() -> (
2508 Pubkey,
2509 AccountSharedData,
2510 AccountSharedData,
2511 Hash,
2512 FeeCalculator,
2513 Option<AccountSharedData>,
2514 ) {
2515 let data = nonce::state::Versions::new_current(nonce::State::Initialized(
2516 nonce::state::Data::default(),
2517 ));
2518 let account = AccountSharedData::new_data(42, &data, &system_program::id()).unwrap();
2519 let mut pre_account = account.clone();
2520 pre_account.set_carats(43);
2521 (
2522 Pubkey::default(),
2523 pre_account,
2524 account,
2525 Hash::new(&[1u8; 32]),
2526 FeeCalculator {
2527 carats_per_signature: 1234,
2528 },
2529 None,
2530 )
2531 }
2532
2533 fn run_prepare_if_nonce_account_test(
2534 account: &mut AccountSharedData,
2535 account_pubkey: &Pubkey,
2536 tx_result: &Result<()>,
2537 maybe_nonce_rollback: Option<(
2538 &Pubkey,
2539 &AccountSharedData,
2540 Option<&AccountSharedData>,
2541 bool,
2542 )>,
2543 last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
2544 expect_account: &AccountSharedData,
2545 ) -> bool {
2546 match maybe_nonce_rollback {
2548 Some((nonce_pubkey, _nonce_account, _maybe_fee_account, _))
2549 if nonce_pubkey == account_pubkey && tx_result.is_ok() =>
2550 {
2551 assert_eq!(expect_account, account) }
2553 Some((nonce_pubkey, nonce_account, _maybe_fee_account, _))
2554 if nonce_pubkey == account_pubkey =>
2555 {
2556 assert_ne!(expect_account, nonce_account)
2557 }
2558 _ => assert_eq!(expect_account, account),
2559 }
2560
2561 prepare_if_nonce_account(
2562 account,
2563 account_pubkey,
2564 tx_result,
2565 maybe_nonce_rollback,
2566 last_blockhash_with_fee_calculator,
2567 );
2568 expect_account == account
2569 }
2570
2571 #[test]
2572 fn test_prepare_if_nonce_account_expected() {
2573 let (
2574 pre_account_pubkey,
2575 pre_account,
2576 mut post_account,
2577 last_blockhash,
2578 last_fee_calculator,
2579 maybe_fee_account,
2580 ) = create_accounts_prepare_if_nonce_account();
2581 let post_account_pubkey = pre_account_pubkey;
2582
2583 let mut expect_account = post_account.clone();
2584 let data = nonce::state::Versions::new_current(nonce::State::Initialized(
2585 nonce::state::Data::default(),
2586 ));
2587 expect_account.set_state(&data).unwrap();
2588
2589 assert!(run_prepare_if_nonce_account_test(
2590 &mut post_account,
2591 &post_account_pubkey,
2592 &Ok(()),
2593 Some((
2594 &pre_account_pubkey,
2595 &pre_account,
2596 maybe_fee_account.as_ref(),
2597 false,
2598 )),
2599 &(last_blockhash, last_fee_calculator),
2600 &expect_account,
2601 ));
2602 }
2603
2604 #[test]
2605 fn test_prepare_if_nonce_account_not_nonce_tx() {
2606 let (
2607 pre_account_pubkey,
2608 _pre_account,
2609 _post_account,
2610 last_blockhash,
2611 last_fee_calculator,
2612 _maybe_fee_account,
2613 ) = create_accounts_prepare_if_nonce_account();
2614 let post_account_pubkey = pre_account_pubkey;
2615
2616 let mut post_account = AccountSharedData::default();
2617 let expect_account = post_account.clone();
2618 assert!(run_prepare_if_nonce_account_test(
2619 &mut post_account,
2620 &post_account_pubkey,
2621 &Ok(()),
2622 None,
2623 &(last_blockhash, last_fee_calculator),
2624 &expect_account,
2625 ));
2626 }
2627
2628 #[test]
2629 fn test_prepare_if_nonce_account_not_nonce_pubkey() {
2630 let (
2631 pre_account_pubkey,
2632 pre_account,
2633 mut post_account,
2634 last_blockhash,
2635 last_fee_calculator,
2636 maybe_fee_account,
2637 ) = create_accounts_prepare_if_nonce_account();
2638
2639 let expect_account = post_account.clone();
2640 assert!(run_prepare_if_nonce_account_test(
2642 &mut post_account,
2643 &Pubkey::new(&[1u8; 32]),
2644 &Ok(()),
2645 Some((
2646 &pre_account_pubkey,
2647 &pre_account,
2648 maybe_fee_account.as_ref(),
2649 true,
2650 )),
2651 &(last_blockhash, last_fee_calculator),
2652 &expect_account,
2653 ));
2654 }
2655
2656 #[test]
2657 fn test_prepare_if_nonce_account_tx_error() {
2658 let (
2659 pre_account_pubkey,
2660 pre_account,
2661 mut post_account,
2662 last_blockhash,
2663 last_fee_calculator,
2664 maybe_fee_account,
2665 ) = create_accounts_prepare_if_nonce_account();
2666 let post_account_pubkey = pre_account_pubkey;
2667
2668 let mut expect_account = pre_account.clone();
2669 expect_account
2670 .set_state(&nonce::state::Versions::new_current(
2671 nonce::State::Initialized(nonce::state::Data {
2672 blockhash: last_blockhash,
2673 fee_calculator: last_fee_calculator.clone(),
2674 ..nonce::state::Data::default()
2675 }),
2676 ))
2677 .unwrap();
2678
2679 assert!(run_prepare_if_nonce_account_test(
2680 &mut post_account,
2681 &post_account_pubkey,
2682 &Err(TransactionError::InstructionError(
2683 0,
2684 InstructionError::InvalidArgument,
2685 )),
2686 Some((
2687 &pre_account_pubkey,
2688 &pre_account,
2689 maybe_fee_account.as_ref(),
2690 true,
2691 )),
2692 &(last_blockhash, last_fee_calculator),
2693 &expect_account,
2694 ));
2695 }
2696
2697 #[test]
2698 fn test_nonced_failure_accounts_rollback_from_pays() {
2699 let rent_collector = RentCollector::default();
2700
2701 let nonce_address = Pubkey::new_unique();
2702 let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
2703 let from = keypair_from_seed(&[1; 32]).unwrap();
2704 let from_address = from.pubkey();
2705 let to_address = Pubkey::new_unique();
2706 let nonce_state =
2707 nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2708 authority: nonce_authority.pubkey(),
2709 blockhash: Hash::new_unique(),
2710 fee_calculator: FeeCalculator::default(),
2711 }));
2712 let nonce_account_post =
2713 AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
2714 let from_account_post = AccountSharedData::new(4199, 0, &Pubkey::default());
2715 let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
2716 let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
2717 let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
2718
2719 let instructions = vec![
2720 system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
2721 system_instruction::transfer(&from_address, &to_address, 42),
2722 ];
2723 let message = Message::new(&instructions, Some(&from_address));
2724 let blockhash = Hash::new_unique();
2725 let transaction_accounts = vec![
2726 (message.account_keys[0], from_account_post),
2727 (message.account_keys[1], nonce_authority_account),
2728 (message.account_keys[2], nonce_account_post),
2729 (message.account_keys[3], to_account),
2730 (message.account_keys[4], recent_blockhashes_sysvar_account),
2731 ];
2732 let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash);
2733
2734 let nonce_state =
2735 nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2736 authority: nonce_authority.pubkey(),
2737 blockhash,
2738 fee_calculator: FeeCalculator::default(),
2739 }));
2740 let nonce_account_pre =
2741 AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
2742 let from_account_pre = AccountSharedData::new(4242, 0, &Pubkey::default());
2743
2744 let nonce_rollback = Some(NonceRollbackFull::new(
2745 nonce_address,
2746 nonce_account_pre.clone(),
2747 Some(from_account_pre.clone()),
2748 ));
2749
2750 let loaded = (
2751 Ok(LoadedTransaction {
2752 accounts: transaction_accounts,
2753 program_indices: vec![],
2754 rent: 0,
2755 rent_debits: RentDebits::default(),
2756 }),
2757 nonce_rollback.clone(),
2758 );
2759
2760 let mut loaded = vec![loaded];
2761
2762 let next_blockhash = Hash::new_unique();
2763 let accounts = Accounts::new_with_config_for_tests(
2764 Vec::new(),
2765 &ClusterType::Development,
2766 AccountSecondaryIndexes::default(),
2767 false,
2768 AccountShrinkThreshold::default(),
2769 );
2770 let txs = vec![tx];
2771 let programs = vec![(
2772 Err(TransactionError::InstructionError(
2773 1,
2774 InstructionError::InvalidArgument,
2775 )),
2776 nonce_rollback,
2777 )];
2778 let collected_accounts = accounts.collect_accounts_to_store(
2779 &txs,
2780 &programs,
2781 loaded.as_mut_slice(),
2782 &rent_collector,
2783 &(next_blockhash, FeeCalculator::default()),
2784 true,
2785 true, true, );
2788 assert_eq!(collected_accounts.len(), 2);
2789 assert_eq!(
2790 collected_accounts
2791 .iter()
2792 .find(|(pubkey, _account)| *pubkey == &from_address)
2793 .map(|(_pubkey, account)| *account)
2794 .cloned()
2795 .unwrap(),
2796 from_account_pre,
2797 );
2798 let collected_nonce_account = collected_accounts
2799 .iter()
2800 .find(|(pubkey, _account)| *pubkey == &nonce_address)
2801 .map(|(_pubkey, account)| *account)
2802 .cloned()
2803 .unwrap();
2804 assert_eq!(
2805 collected_nonce_account.carats(),
2806 nonce_account_pre.carats(),
2807 );
2808 assert!(nonce_account::verify_nonce_account(
2809 &collected_nonce_account,
2810 &next_blockhash
2811 ));
2812 }
2813
2814 #[test]
2815 fn test_nonced_failure_accounts_rollback_nonce_pays() {
2816 let rent_collector = RentCollector::default();
2817
2818 let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
2819 let nonce_address = nonce_authority.pubkey();
2820 let from = keypair_from_seed(&[1; 32]).unwrap();
2821 let from_address = from.pubkey();
2822 let to_address = Pubkey::new_unique();
2823 let nonce_state =
2824 nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2825 authority: nonce_authority.pubkey(),
2826 blockhash: Hash::new_unique(),
2827 fee_calculator: FeeCalculator::default(),
2828 }));
2829 let nonce_account_post =
2830 AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
2831 let from_account_post = AccountSharedData::new(4200, 0, &Pubkey::default());
2832 let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
2833 let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
2834 let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
2835
2836 let instructions = vec![
2837 system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
2838 system_instruction::transfer(&from_address, &to_address, 42),
2839 ];
2840 let message = Message::new(&instructions, Some(&nonce_address));
2841 let blockhash = Hash::new_unique();
2842 let transaction_accounts = vec![
2843 (message.account_keys[0], from_account_post),
2844 (message.account_keys[1], nonce_authority_account),
2845 (message.account_keys[2], nonce_account_post),
2846 (message.account_keys[3], to_account),
2847 (message.account_keys[4], recent_blockhashes_sysvar_account),
2848 ];
2849 let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash);
2850
2851 let nonce_state =
2852 nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2853 authority: nonce_authority.pubkey(),
2854 blockhash,
2855 fee_calculator: FeeCalculator::default(),
2856 }));
2857 let nonce_account_pre =
2858 AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
2859
2860 let nonce_rollback = Some(NonceRollbackFull::new(
2861 nonce_address,
2862 nonce_account_pre.clone(),
2863 None,
2864 ));
2865
2866 let loaded = (
2867 Ok(LoadedTransaction {
2868 accounts: transaction_accounts,
2869 program_indices: vec![],
2870 rent: 0,
2871 rent_debits: RentDebits::default(),
2872 }),
2873 nonce_rollback.clone(),
2874 );
2875
2876 let mut loaded = vec![loaded];
2877
2878 let next_blockhash = Hash::new_unique();
2879 let accounts = Accounts::new_with_config_for_tests(
2880 Vec::new(),
2881 &ClusterType::Development,
2882 AccountSecondaryIndexes::default(),
2883 false,
2884 AccountShrinkThreshold::default(),
2885 );
2886 let txs = vec![tx];
2887 let programs = vec![(
2888 Err(TransactionError::InstructionError(
2889 1,
2890 InstructionError::InvalidArgument,
2891 )),
2892 nonce_rollback,
2893 )];
2894 let collected_accounts = accounts.collect_accounts_to_store(
2895 &txs,
2896 &programs,
2897 loaded.as_mut_slice(),
2898 &rent_collector,
2899 &(next_blockhash, FeeCalculator::default()),
2900 true,
2901 true, true, );
2904 assert_eq!(collected_accounts.len(), 1);
2905 let collected_nonce_account = collected_accounts
2906 .iter()
2907 .find(|(pubkey, _account)| *pubkey == &nonce_address)
2908 .map(|(_pubkey, account)| *account)
2909 .cloned()
2910 .unwrap();
2911 assert_eq!(
2912 collected_nonce_account.carats(),
2913 nonce_account_pre.carats()
2914 );
2915 assert!(nonce_account::verify_nonce_account(
2916 &collected_nonce_account,
2917 &next_blockhash
2918 ));
2919 }
2920
2921 #[test]
2922 fn test_load_largest_accounts() {
2923 let accounts = Accounts::new_with_config_for_tests(
2924 Vec::new(),
2925 &ClusterType::Development,
2926 AccountSecondaryIndexes::default(),
2927 false,
2928 AccountShrinkThreshold::default(),
2929 );
2930
2931 let pubkey0 = Pubkey::new_unique();
2932 let account0 = AccountSharedData::new(42, 0, &Pubkey::default());
2933 accounts.store_slow_uncached(0, &pubkey0, &account0);
2934 let pubkey1 = Pubkey::new_unique();
2935 let account1 = AccountSharedData::new(42, 0, &Pubkey::default());
2936 accounts.store_slow_uncached(0, &pubkey1, &account1);
2937 let pubkey2 = Pubkey::new_unique();
2938 let account2 = AccountSharedData::new(41, 0, &Pubkey::default());
2939 accounts.store_slow_uncached(0, &pubkey2, &account2);
2940
2941 let ancestors = vec![(0, 0)].into_iter().collect();
2942 let all_pubkeys: HashSet<_> = vec![pubkey0, pubkey1, pubkey2].into_iter().collect();
2943
2944 let bank_id = 0;
2946 assert_eq!(
2947 accounts
2948 .load_largest_accounts(
2949 &ancestors,
2950 bank_id,
2951 0,
2952 &HashSet::new(),
2953 AccountAddressFilter::Exclude
2954 )
2955 .unwrap(),
2956 vec![]
2957 );
2958 assert_eq!(
2959 accounts
2960 .load_largest_accounts(
2961 &ancestors,
2962 bank_id,
2963 0,
2964 &all_pubkeys,
2965 AccountAddressFilter::Include
2966 )
2967 .unwrap(),
2968 vec![]
2969 );
2970
2971 assert!(pubkey1 > pubkey0);
2973 assert_eq!(
2974 accounts
2975 .load_largest_accounts(
2976 &ancestors,
2977 bank_id,
2978 1,
2979 &HashSet::new(),
2980 AccountAddressFilter::Exclude
2981 )
2982 .unwrap(),
2983 vec![(pubkey1, 42)]
2984 );
2985 assert_eq!(
2986 accounts
2987 .load_largest_accounts(
2988 &ancestors,
2989 bank_id,
2990 2,
2991 &HashSet::new(),
2992 AccountAddressFilter::Exclude
2993 )
2994 .unwrap(),
2995 vec![(pubkey1, 42), (pubkey0, 42)]
2996 );
2997 assert_eq!(
2998 accounts
2999 .load_largest_accounts(
3000 &ancestors,
3001 bank_id,
3002 3,
3003 &HashSet::new(),
3004 AccountAddressFilter::Exclude
3005 )
3006 .unwrap(),
3007 vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)]
3008 );
3009
3010 assert_eq!(
3012 accounts
3013 .load_largest_accounts(
3014 &ancestors,
3015 bank_id,
3016 6,
3017 &HashSet::new(),
3018 AccountAddressFilter::Exclude
3019 )
3020 .unwrap(),
3021 vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)]
3022 );
3023
3024 let exclude1: HashSet<_> = vec![pubkey1].into_iter().collect();
3026 assert_eq!(
3027 accounts
3028 .load_largest_accounts(
3029 &ancestors,
3030 bank_id,
3031 1,
3032 &exclude1,
3033 AccountAddressFilter::Exclude
3034 )
3035 .unwrap(),
3036 vec![(pubkey0, 42)]
3037 );
3038 assert_eq!(
3039 accounts
3040 .load_largest_accounts(
3041 &ancestors,
3042 bank_id,
3043 2,
3044 &exclude1,
3045 AccountAddressFilter::Exclude
3046 )
3047 .unwrap(),
3048 vec![(pubkey0, 42), (pubkey2, 41)]
3049 );
3050 assert_eq!(
3051 accounts
3052 .load_largest_accounts(
3053 &ancestors,
3054 bank_id,
3055 3,
3056 &exclude1,
3057 AccountAddressFilter::Exclude
3058 )
3059 .unwrap(),
3060 vec![(pubkey0, 42), (pubkey2, 41)]
3061 );
3062
3063 let include1_2: HashSet<_> = vec![pubkey1, pubkey2].into_iter().collect();
3065 assert_eq!(
3066 accounts
3067 .load_largest_accounts(
3068 &ancestors,
3069 bank_id,
3070 1,
3071 &include1_2,
3072 AccountAddressFilter::Include
3073 )
3074 .unwrap(),
3075 vec![(pubkey1, 42)]
3076 );
3077 assert_eq!(
3078 accounts
3079 .load_largest_accounts(
3080 &ancestors,
3081 bank_id,
3082 2,
3083 &include1_2,
3084 AccountAddressFilter::Include
3085 )
3086 .unwrap(),
3087 vec![(pubkey1, 42), (pubkey2, 41)]
3088 );
3089 assert_eq!(
3090 accounts
3091 .load_largest_accounts(
3092 &ancestors,
3093 bank_id,
3094 3,
3095 &include1_2,
3096 AccountAddressFilter::Include
3097 )
3098 .unwrap(),
3099 vec![(pubkey1, 42), (pubkey2, 41)]
3100 );
3101 }
3102}