Add circ/non-circ filter to getLargestAccounts (#10188)

This commit is contained in:
Tyera Eulberg
2020-05-22 15:14:18 -06:00
committed by GitHub
parent ee1f218e76
commit 33322d9501
4 changed files with 84 additions and 36 deletions

View File

@ -8,6 +8,7 @@ pub mod perf_utils;
pub mod pubsub_client;
pub mod rpc_client;
pub mod rpc_client_request;
pub mod rpc_config;
pub mod rpc_request;
pub mod rpc_response;
pub mod thin_client;

View File

@ -3,7 +3,10 @@ use solana_sdk::commitment_config::CommitmentConfig;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSignatureStatusConfig {
pub search_transaction_history: bool,
pub search_transaction_history: Option<bool>,
// DEPRECATED
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]

View File

@ -18,6 +18,7 @@ pub enum RpcRequest {
GetGenesisHash,
GetIdentity,
GetInflation,
GetLargestAccounts,
GetLeaderSchedule,
GetProgramAccounts,
GetRecentBlockhash,
@ -61,6 +62,7 @@ impl RpcRequest {
RpcRequest::GetGenesisHash => "getGenesisHash",
RpcRequest::GetIdentity => "getIdentity",
RpcRequest::GetInflation => "getInflation",
RpcRequest::GetLargestAccounts => "getLargestAccounts",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetProgramAccounts => "getProgramAccounts",
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",

View File

@ -13,7 +13,7 @@ use crate::{
use bincode::serialize;
use jsonrpc_core::{Error, Metadata, Result};
use jsonrpc_derive::rpc;
use solana_client::rpc_response::*;
use solana_client::{rpc_config::*, rpc_response::*};
use solana_faucet::faucet::request_airdrop_transaction;
use solana_ledger::{
bank_forks::BankForks, blockstore::Blockstore, blockstore_db::BlockstoreError,
@ -64,21 +64,6 @@ pub struct JsonRpcConfig {
pub faucet_addr: Option<SocketAddr>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSignatureStatusConfig {
pub search_transaction_history: Option<bool>,
// DEPRECATED
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcSimulateTransactionConfig {
pub sig_verify: bool,
}
#[derive(Clone)]
pub struct JsonRpcRequestProcessor {
bank_forks: Arc<RwLock<BankForks>>,
@ -287,22 +272,30 @@ impl JsonRpcRequestProcessor {
fn get_largest_accounts(
&self,
commitment: Option<CommitmentConfig>,
config: Option<RpcLargestAccountsConfig>,
) -> RpcResponse<Vec<RpcAccountBalance>> {
let bank = self.bank(commitment)?;
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment)?;
let (addresses, address_filter) = if let Some(filter) = config.filter {
let non_circulating_supply = calculate_non_circulating_supply(&bank);
let addresses = non_circulating_supply.accounts.into_iter().collect();
let address_filter = match filter {
RpcLargestAccountsFilter::Circulating => AccountAddressFilter::Exclude,
RpcLargestAccountsFilter::NonCirculating => AccountAddressFilter::Include,
};
(addresses, address_filter)
} else {
(HashSet::new(), AccountAddressFilter::Exclude)
};
new_response(
&bank,
bank.get_largest_accounts(
NUM_LARGEST_ACCOUNTS,
&HashSet::new(),
AccountAddressFilter::Exclude,
)
.into_iter()
.map(|(address, lamports)| RpcAccountBalance {
address: address.to_string(),
lamports,
})
.collect(),
bank.get_largest_accounts(NUM_LARGEST_ACCOUNTS, &addresses, address_filter)
.into_iter()
.map(|(address, lamports)| RpcAccountBalance {
address: address.to_string(),
lamports,
})
.collect(),
)
}
@ -851,7 +844,7 @@ pub trait RpcSol {
fn get_largest_accounts(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcLargestAccountsConfig>,
) -> RpcResponse<Vec<RpcAccountBalance>>;
#[rpc(meta, name = "getSupply")]
@ -1276,13 +1269,13 @@ impl RpcSol for RpcSolImpl {
fn get_largest_accounts(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
config: Option<RpcLargestAccountsConfig>,
) -> RpcResponse<Vec<RpcAccountBalance>> {
debug!("get_largest_accounts rpc request received");
meta.request_processor
.read()
.unwrap()
.get_largest_accounts(commitment)
.get_largest_accounts(config)
}
fn get_supply(
@ -1637,6 +1630,7 @@ pub mod tests {
commitment::BlockCommitment,
contact_info::ContactInfo,
genesis_utils::{create_genesis_config, GenesisConfigInfo},
non_circulating_supply::non_circulating_accounts,
replay_stage::tests::create_test_transactions_and_populate_blockstore,
};
use bincode::deserialize;
@ -1786,6 +1780,9 @@ pub mod tests {
let blockhash = bank.confirmed_last_blockhash().0;
let tx = system_transaction::transfer(&alice, pubkey, 20, blockhash);
bank.process_transaction(&tx).expect("process transaction");
let tx =
system_transaction::transfer(&alice, &non_circulating_accounts()[0], 20, blockhash);
bank.process_transaction(&tx).expect("process transaction");
let tx = system_transaction::transfer(&alice, pubkey, std::u64::MAX, blockhash);
let _ = bank.process_transaction(&tx);
@ -1942,7 +1939,7 @@ pub mod tests {
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getTransactionCount"}}"#);
let res = io.handle_request_sync(&req, meta);
let expected = format!(r#"{{"jsonrpc":"2.0","result":3,"id":1}}"#);
let expected = format!(r#"{{"jsonrpc":"2.0","result":4,"id":1}}"#);
let expected: Response =
serde_json::from_str(&expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response"))
@ -1990,6 +1987,31 @@ pub mod tests {
assert!(supply >= TEST_MINT_LAMPORTS);
}
#[test]
fn test_get_supply() {
let bob_pubkey = Pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getSupply"}}"#);
let res = io.handle_request_sync(&req, meta.clone());
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let supply: RpcSupply = serde_json::from_value(json["result"]["value"].clone())
.expect("actual response deserialization");
assert_eq!(supply.non_circulating, 20);
assert!(supply.circulating >= TEST_MINT_LAMPORTS);
assert!(supply.total >= TEST_MINT_LAMPORTS + 20);
let expected_accounts: Vec<String> = non_circulating_accounts()
.iter()
.map(|pubkey| pubkey.to_string())
.collect();
assert_eq!(
supply.non_circulating_accounts.len(),
expected_accounts.len()
);
for address in supply.non_circulating_accounts {
assert!(expected_accounts.contains(&address));
}
}
#[test]
fn test_get_largest_accounts() {
let bob_pubkey = Pubkey::new_rand();
@ -2002,7 +2024,7 @@ pub mod tests {
let largest_accounts: Vec<RpcAccountBalance> =
serde_json::from_value(json["result"]["value"].clone())
.expect("actual response deserialization");
assert_eq!(largest_accounts.len(), 18);
assert_eq!(largest_accounts.len(), 19);
// Get Alice balance
let req = format!(
@ -2023,7 +2045,7 @@ pub mod tests {
r#"{{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["{}"]}}"#,
bob_pubkey
);
let res = io.handle_request_sync(&req, meta);
let res = io.handle_request_sync(&req, meta.clone());
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let bob_balance: u64 = serde_json::from_value(json["result"]["value"].clone())
.expect("actual response deserialization");
@ -2031,6 +2053,26 @@ pub mod tests {
address: bob_pubkey.to_string(),
lamports: bob_balance,
}));
// Test Circulating/NonCirculating Filter
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getLargestAccounts","params":[{{"filter":"circulating"}}]}}"#
);
let res = io.handle_request_sync(&req, meta.clone());
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let largest_accounts: Vec<RpcAccountBalance> =
serde_json::from_value(json["result"]["value"].clone())
.expect("actual response deserialization");
assert_eq!(largest_accounts.len(), 18);
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getLargestAccounts","params":[{{"filter":"nonCirculating"}}]}}"#
);
let res = io.handle_request_sync(&req, meta.clone());
let json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let largest_accounts: Vec<RpcAccountBalance> =
serde_json::from_value(json["result"]["value"].clone())
.expect("actual response deserialization");
assert_eq!(largest_accounts.len(), 1);
}
#[test]