diff --git a/core/src/non_circulating_supply.rs b/core/src/non_circulating_supply.rs index de514996a6..bebd2ac6e2 100644 --- a/core/src/non_circulating_supply.rs +++ b/core/src/non_circulating_supply.rs @@ -1,4 +1,7 @@ -use solana_runtime::bank::Bank; +use solana_runtime::{ + accounts_index::{AccountIndex, IndexKey}, + bank::Bank, +}; use solana_sdk::pubkey::Pubkey; use solana_stake_program::stake_state::StakeState; use std::{collections::HashSet, sync::Arc}; @@ -18,7 +21,24 @@ pub fn calculate_non_circulating_supply(bank: &Arc) -> NonCirculatingSuppl let withdraw_authority_list = withdraw_authority(); let clock = bank.clock(); - let stake_accounts = bank.get_program_accounts(&solana_stake_program::id()); + let stake_accounts = if bank + .rc + .accounts + .accounts_db + .account_indexes + .contains(&AccountIndex::ProgramId) + { + bank.get_filtered_indexed_accounts( + &IndexKey::ProgramId(solana_stake_program::id()), + // The program-id account index checks for Account owner on inclusion. However, due to + // the current AccountsDB implementation, an account may remain in storage as a + // zero-lamport Account::Default() after being wiped and reinitialized in later + // updates. We include the redundant filter here to avoid returning these accounts. + |account| account.owner == solana_stake_program::id(), + ) + } else { + bank.get_program_accounts(&solana_stake_program::id()) + }; for (pubkey, account) in stake_accounts.iter() { let stake_account = StakeState::from(&account).unwrap_or_default(); match stake_account { diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 72b33c32c4..3d93bec094 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -1313,6 +1313,11 @@ impl JsonRpcRequestProcessor { .contains(&AccountIndex::ProgramId) { bank.get_filtered_indexed_accounts(&IndexKey::ProgramId(*program_id), |account| { + // The program-id account index checks for Account owner on inclusion. However, due + // to the current AccountsDB implementation, an account may remain in storage as a + // zero-lamport Account::Default() after being wiped and reinitialized in later + // updates. We include the redundant filters here to avoid returning these + // accounts. account.owner == *program_id && filter_closure(account) }) } else { @@ -1327,10 +1332,10 @@ impl JsonRpcRequestProcessor { owner_key: &Pubkey, mut filters: Vec, ) -> Vec<(Pubkey, Account)> { - // The by-owner accounts index checks for Token Account state and Owner address on inclusion. - // However, due to the current AccountsDB implementation, accounts may remain in storage as - // be zero-lamport Account::Default() after being wiped and reinitialized in a later updates. - // We include the redundant filters here to avoid returning these accounts. + // The by-owner accounts index checks for Token Account state and Owner address on + // inclusion. However, due to the current AccountsDB implementation, an account may remain + // in storage as a zero-lamport Account::Default() after being wiped and reinitialized in + // later updates. We include the redundant filters here to avoid returning these accounts. // // Filter on Token Account state filters.push(RpcFilterType::DataSize( @@ -1368,9 +1373,9 @@ impl JsonRpcRequestProcessor { mut filters: Vec, ) -> Vec<(Pubkey, Account)> { // The by-mint accounts index checks for Token Account state and Mint address on inclusion. - // However, due to the current AccountsDB implementation, accounts may remain in storage as - // be zero-lamport Account::Default() after being wiped and reinitialized in a later updates. - // We include the redundant filters here to avoid returning these accounts. + // However, due to the current AccountsDB implementation, an account may remain in storage + // as be zero-lamport Account::Default() after being wiped and reinitialized in later + // updates. We include the redundant filters here to avoid returning these accounts. // // Filter on Token Account state filters.push(RpcFilterType::DataSize(