diff --git a/accounts-db/benches/accounts.rs b/accounts-db/benches/accounts.rs index 6c3f26ebfd3b41..202a220e10e425 100644 --- a/accounts-db/benches/accounts.rs +++ b/accounts-db/benches/accounts.rs @@ -340,6 +340,7 @@ fn bench_load_largest_accounts(b: &mut Bencher) { 20, &HashSet::new(), AccountAddressFilter::Exclude, + false, ) }); } diff --git a/accounts-db/src/accounts.rs b/accounts-db/src/accounts.rs index 49dbeca3437f61..1d4086b0c652dc 100644 --- a/accounts-db/src/accounts.rs +++ b/accounts-db/src/accounts.rs @@ -254,6 +254,7 @@ impl Accounts { num: usize, filter_by_address: &HashSet, filter: AccountAddressFilter, + sort_results: bool, ) -> ScanResult> { if num == 0 { return Ok(vec![]); @@ -287,7 +288,7 @@ impl Accounts { account_balances.push(Reverse((account.lamports(), *pubkey))); } }, - &ScanConfig::default(), + &ScanConfig::new(!sort_results), )?; Ok(account_balances .into_sorted_vec() @@ -480,6 +481,7 @@ impl Accounts { &self, ancestors: &Ancestors, bank_id: BankId, + sort_results: bool, ) -> ScanResult> { let mut collector = Vec::new(); self.accounts_db @@ -493,7 +495,7 @@ impl Accounts { collector.push((*pubkey, account, slot)) } }, - &ScanConfig::default(), + &ScanConfig::new(!sort_results), ) .map(|_| collector) } @@ -503,12 +505,17 @@ impl Accounts { ancestors: &Ancestors, bank_id: BankId, scan_func: F, + sort_results: bool, ) -> ScanResult<()> where F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>), { - self.accounts_db - .scan_accounts(ancestors, bank_id, scan_func, &ScanConfig::default()) + self.accounts_db.scan_accounts( + ancestors, + bank_id, + scan_func, + &ScanConfig::new(!sort_results), + ) } pub fn hold_range_in_memory( @@ -534,7 +541,7 @@ impl Accounts { "", // disable logging of this. We now parallelize it and this results in multiple parallel logs ancestors, range, - &ScanConfig::new(true), + &ScanConfig::default(), |option| Self::load_with_slot(&mut collector, option), ); collector @@ -2153,7 +2160,8 @@ mod tests { bank_id, 0, &HashSet::new(), - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![] @@ -2165,7 +2173,8 @@ mod tests { bank_id, 0, &all_pubkeys, - AccountAddressFilter::Include + AccountAddressFilter::Include, + false ) .unwrap(), vec![] @@ -2180,7 +2189,8 @@ mod tests { bank_id, 1, &HashSet::new(), - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![(pubkey1, 42)] @@ -2192,7 +2202,8 @@ mod tests { bank_id, 2, &HashSet::new(), - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![(pubkey1, 42), (pubkey0, 42)] @@ -2204,7 +2215,8 @@ mod tests { bank_id, 3, &HashSet::new(), - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)] @@ -2218,7 +2230,8 @@ mod tests { bank_id, 6, &HashSet::new(), - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)] @@ -2233,7 +2246,8 @@ mod tests { bank_id, 1, &exclude1, - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![(pubkey0, 42)] @@ -2245,7 +2259,8 @@ mod tests { bank_id, 2, &exclude1, - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![(pubkey0, 42), (pubkey2, 41)] @@ -2257,7 +2272,8 @@ mod tests { bank_id, 3, &exclude1, - AccountAddressFilter::Exclude + AccountAddressFilter::Exclude, + false ) .unwrap(), vec![(pubkey0, 42), (pubkey2, 41)] @@ -2272,7 +2288,8 @@ mod tests { bank_id, 1, &include1_2, - AccountAddressFilter::Include + AccountAddressFilter::Include, + false ) .unwrap(), vec![(pubkey1, 42)] @@ -2284,7 +2301,8 @@ mod tests { bank_id, 2, &include1_2, - AccountAddressFilter::Include + AccountAddressFilter::Include, + false ) .unwrap(), vec![(pubkey1, 42), (pubkey2, 41)] @@ -2296,7 +2314,8 @@ mod tests { bank_id, 3, &include1_2, - AccountAddressFilter::Include + AccountAddressFilter::Include, + false ) .unwrap(), vec![(pubkey1, 42), (pubkey2, 41)] @@ -2324,7 +2343,10 @@ mod tests { #[test] fn test_maybe_abort_scan() { assert!(Accounts::maybe_abort_scan(ScanResult::Ok(vec![]), &ScanConfig::default()).is_ok()); - let config = ScanConfig::default().recreate_with_abort(); + assert!( + Accounts::maybe_abort_scan(ScanResult::Ok(vec![]), &ScanConfig::new(false)).is_ok() + ); + let config = ScanConfig::new(false).recreate_with_abort(); assert!(Accounts::maybe_abort_scan(ScanResult::Ok(vec![]), &config).is_ok()); config.abort(); assert!(Accounts::maybe_abort_scan(ScanResult::Ok(vec![]), &config).is_err()); diff --git a/accounts-db/src/accounts_index.rs b/accounts-db/src/accounts_index.rs index bea586d762342f..607304789da809 100644 --- a/accounts-db/src/accounts_index.rs +++ b/accounts-db/src/accounts_index.rs @@ -90,7 +90,7 @@ pub enum UpsertReclaim { IgnoreReclaims, } -#[derive(Debug, Default)] +#[derive(Debug)] pub struct ScanConfig { /// checked by the scan. When true, abort scan. pub abort: Option>, @@ -100,11 +100,20 @@ pub struct ScanConfig { pub collect_all_unsorted: bool, } +impl Default for ScanConfig { + fn default() -> Self { + Self { + abort: None, + collect_all_unsorted: true, + } + } +} + impl ScanConfig { pub fn new(collect_all_unsorted: bool) -> Self { Self { collect_all_unsorted, - ..ScanConfig::default() + ..Default::default() } } @@ -4214,10 +4223,14 @@ pub mod tests { assert!(!config.is_aborted()); } - let config = ScanConfig::default(); + let config = ScanConfig::new(false); assert!(!config.collect_all_unsorted); assert!(config.abort.is_none()); + let config = ScanConfig::default(); + assert!(config.collect_all_unsorted); + assert!(config.abort.is_none()); + let config = config.recreate_with_abort(); assert!(config.abort.is_some()); assert!(!config.is_aborted()); diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 4893f3a791a82e..0a26dd14e7be66 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -1443,6 +1443,7 @@ pub fn process_largest_accounts( .get_largest_accounts_with_config(RpcLargestAccountsConfig { commitment: Some(config.commitment), filter, + sort_results: None, })? .value; let largest_accounts = CliAccountBalances { accounts }; diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index 7a41758da291a0..2e0da8e18ded18 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -2032,7 +2032,7 @@ fn main() { if remove_stake_accounts { for (address, mut account) in bank - .get_program_accounts(&stake::program::id(), &ScanConfig::default()) + .get_program_accounts(&stake::program::id(), &ScanConfig::new(false)) .unwrap() .into_iter() { @@ -2082,7 +2082,7 @@ fn main() { if !vote_accounts_to_destake.is_empty() { for (address, mut account) in bank - .get_program_accounts(&stake::program::id(), &ScanConfig::default()) + .get_program_accounts(&stake::program::id(), &ScanConfig::new(false)) .unwrap() .into_iter() { @@ -2122,7 +2122,7 @@ fn main() { for (address, mut account) in bank .get_program_accounts( &solana_vote_program::id(), - &ScanConfig::default(), + &ScanConfig::new(false), ) .unwrap() .into_iter() diff --git a/ledger-tool/src/output.rs b/ledger-tool/src/output.rs index 3de08cec989806..d798976357c85b 100644 --- a/ledger-tool/src/output.rs +++ b/ledger-tool/src/output.rs @@ -656,7 +656,7 @@ impl AccountsScanner { match &self.config.mode { AccountsOutputMode::All => { - self.bank.scan_all_accounts(scan_func).unwrap(); + self.bank.scan_all_accounts(scan_func, true).unwrap(); } AccountsOutputMode::Individual(pubkeys) => pubkeys.iter().for_each(|pubkey| { if let Some((account, slot)) = self @@ -676,7 +676,7 @@ impl AccountsScanner { }), AccountsOutputMode::Program(program_pubkey) => self .bank - .get_program_accounts(program_pubkey, &ScanConfig::default()) + .get_program_accounts(program_pubkey, &ScanConfig::new(false)) .unwrap() .iter() .filter(|(_, account)| self.should_process_account(account)) diff --git a/rpc-client-api/src/config.rs b/rpc-client-api/src/config.rs index 9bf1819b32d0a2..db13ea1280d829 100644 --- a/rpc-client-api/src/config.rs +++ b/rpc-client-api/src/config.rs @@ -119,6 +119,7 @@ pub struct RpcLargestAccountsConfig { #[serde(flatten)] pub commitment: Option, pub filter: Option, + pub sort_results: Option, } #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] diff --git a/rpc-client/src/nonblocking/rpc_client.rs b/rpc-client/src/nonblocking/rpc_client.rs index fceb338e20756e..f6234e5367ccaf 100644 --- a/rpc-client/src/nonblocking/rpc_client.rs +++ b/rpc-client/src/nonblocking/rpc_client.rs @@ -2257,6 +2257,7 @@ impl RpcClient { /// let config = RpcLargestAccountsConfig { /// commitment: Some(commitment_config), /// filter: Some(RpcLargestAccountsFilter::Circulating), + /// sort_results: None, /// }; /// let accounts = rpc_client.get_largest_accounts_with_config( /// config, diff --git a/rpc-client/src/rpc_client.rs b/rpc-client/src/rpc_client.rs index 119039269a7bac..b8cbba11d1eebd 100644 --- a/rpc-client/src/rpc_client.rs +++ b/rpc-client/src/rpc_client.rs @@ -1872,6 +1872,7 @@ impl RpcClient { /// let config = RpcLargestAccountsConfig { /// commitment: Some(commitment_config), /// filter: Some(RpcLargestAccountsFilter::Circulating), + /// sort_results: None, /// }; /// let accounts = rpc_client.get_largest_accounts_with_config( /// config, diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index 52ba4010710cf6..1d5d07d9136f40 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -872,6 +872,7 @@ impl JsonRpcRequestProcessor { ) -> RpcCustomResult>> { let config = config.unwrap_or_default(); let bank = self.bank(config.commitment); + let sort_results = config.sort_results.unwrap_or(true); if let Some((slot, accounts)) = self.get_cached_largest_accounts(&config.filter) { Ok(RpcResponse { @@ -896,7 +897,12 @@ impl JsonRpcRequestProcessor { (HashSet::new(), AccountAddressFilter::Exclude) }; let accounts = bank - .get_largest_accounts(NUM_LARGEST_ACCOUNTS, &addresses, address_filter) + .get_largest_accounts( + NUM_LARGEST_ACCOUNTS, + &addresses, + address_filter, + sort_results, + ) .map_err(|e| RpcCustomError::ScanError { message: e.to_string(), })? diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 87bfc34405d0d3..a9d3fd4ec1b930 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -5304,18 +5304,20 @@ impl Bank { } /// Returns all the accounts this bank can load - pub fn get_all_accounts(&self) -> ScanResult> { - self.rc.accounts.load_all(&self.ancestors, self.bank_id) + pub fn get_all_accounts(&self, sort_results: bool) -> ScanResult> { + self.rc + .accounts + .load_all(&self.ancestors, self.bank_id, sort_results) } // Scans all the accounts this bank can load, applying `scan_func` - pub fn scan_all_accounts(&self, scan_func: F) -> ScanResult<()> + pub fn scan_all_accounts(&self, scan_func: F, sort_results: bool) -> ScanResult<()> where F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>), { self.rc .accounts - .scan_all(&self.ancestors, self.bank_id, scan_func) + .scan_all(&self.ancestors, self.bank_id, scan_func, sort_results) } pub fn get_program_accounts_modified_since_parent( @@ -5361,6 +5363,7 @@ impl Bank { num: usize, filter_by_address: &HashSet, filter: AccountAddressFilter, + sort_results: bool, ) -> ScanResult> { self.rc.accounts.load_largest_accounts( &self.ancestors, @@ -5368,6 +5371,7 @@ impl Bank { num, filter_by_address, filter, + sort_results, ) } @@ -6643,7 +6647,7 @@ impl Bank { /// Get all the accounts for this bank and calculate stats pub fn get_total_accounts_stats(&self) -> ScanResult { - let accounts = self.get_all_accounts()?; + let accounts = self.get_all_accounts(false)?; Ok(self.calculate_total_accounts_stats( accounts .iter() diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index a4e538b128b6dc..d7fa26cae00658 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -4349,7 +4349,7 @@ fn test_bank_get_program_accounts() { let parent = Arc::new(Bank::new_for_tests(&genesis_config)); parent.restore_old_behavior_for_fragile_tests(); - let genesis_accounts: Vec<_> = parent.get_all_accounts().unwrap(); + let genesis_accounts: Vec<_> = parent.get_all_accounts(false).unwrap(); assert!( genesis_accounts .iter() @@ -9473,24 +9473,24 @@ fn test_get_largest_accounts() { // Return only one largest account assert_eq!( - bank.get_largest_accounts(1, &pubkeys_hashset, AccountAddressFilter::Include) + bank.get_largest_accounts(1, &pubkeys_hashset, AccountAddressFilter::Include, false) .unwrap(), vec![(pubkeys[4], sol_to_lamports(5.0))] ); assert_eq!( - bank.get_largest_accounts(1, &HashSet::new(), AccountAddressFilter::Exclude) + bank.get_largest_accounts(1, &HashSet::new(), AccountAddressFilter::Exclude, false) .unwrap(), vec![(pubkeys[4], sol_to_lamports(5.0))] ); assert_eq!( - bank.get_largest_accounts(1, &exclude4, AccountAddressFilter::Exclude) + bank.get_largest_accounts(1, &exclude4, AccountAddressFilter::Exclude, false) .unwrap(), vec![(pubkeys[3], sol_to_lamports(4.0))] ); // Return all added accounts let results = bank - .get_largest_accounts(10, &pubkeys_hashset, AccountAddressFilter::Include) + .get_largest_accounts(10, &pubkeys_hashset, AccountAddressFilter::Include, false) .unwrap(); assert_eq!(results.len(), sorted_accounts.len()); for pubkey_balance in sorted_accounts.iter() { @@ -9502,7 +9502,7 @@ fn test_get_largest_accounts() { let expected_accounts = sorted_accounts[1..].to_vec(); let results = bank - .get_largest_accounts(10, &exclude4, AccountAddressFilter::Exclude) + .get_largest_accounts(10, &exclude4, AccountAddressFilter::Exclude, false) .unwrap(); // results include 5 Bank builtins assert_eq!(results.len(), 10); @@ -9516,7 +9516,7 @@ fn test_get_largest_accounts() { // Return 3 added accounts let expected_accounts = sorted_accounts[0..4].to_vec(); let results = bank - .get_largest_accounts(4, &pubkeys_hashset, AccountAddressFilter::Include) + .get_largest_accounts(4, &pubkeys_hashset, AccountAddressFilter::Include, false) .unwrap(); assert_eq!(results.len(), expected_accounts.len()); for pubkey_balance in expected_accounts.iter() { @@ -9525,7 +9525,7 @@ fn test_get_largest_accounts() { let expected_accounts = expected_accounts[1..4].to_vec(); let results = bank - .get_largest_accounts(3, &exclude4, AccountAddressFilter::Exclude) + .get_largest_accounts(3, &exclude4, AccountAddressFilter::Exclude, false) .unwrap(); assert_eq!(results.len(), expected_accounts.len()); for pubkey_balance in expected_accounts.iter() { @@ -9538,7 +9538,7 @@ fn test_get_largest_accounts() { .cloned() .collect(); assert_eq!( - bank.get_largest_accounts(2, &exclude, AccountAddressFilter::Exclude) + bank.get_largest_accounts(2, &exclude, AccountAddressFilter::Exclude, false) .unwrap(), vec![pubkeys_balances[3], pubkeys_balances[1]] );