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 pubsub_client;
pub mod rpc_client; pub mod rpc_client;
pub mod rpc_client_request; pub mod rpc_client_request;
pub mod rpc_config;
pub mod rpc_request; pub mod rpc_request;
pub mod rpc_response; pub mod rpc_response;
pub mod thin_client; pub mod thin_client;

View File

@ -3,7 +3,10 @@ use solana_sdk::commitment_config::CommitmentConfig;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RpcSignatureStatusConfig { 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)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]

View File

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

View File

@ -13,7 +13,7 @@ use crate::{
use bincode::serialize; use bincode::serialize;
use jsonrpc_core::{Error, Metadata, Result}; use jsonrpc_core::{Error, Metadata, Result};
use jsonrpc_derive::rpc; 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_faucet::faucet::request_airdrop_transaction;
use solana_ledger::{ use solana_ledger::{
bank_forks::BankForks, blockstore::Blockstore, blockstore_db::BlockstoreError, bank_forks::BankForks, blockstore::Blockstore, blockstore_db::BlockstoreError,
@ -64,21 +64,6 @@ pub struct JsonRpcConfig {
pub faucet_addr: Option<SocketAddr>, 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)] #[derive(Clone)]
pub struct JsonRpcRequestProcessor { pub struct JsonRpcRequestProcessor {
bank_forks: Arc<RwLock<BankForks>>, bank_forks: Arc<RwLock<BankForks>>,
@ -287,22 +272,30 @@ impl JsonRpcRequestProcessor {
fn get_largest_accounts( fn get_largest_accounts(
&self, &self,
commitment: Option<CommitmentConfig>, config: Option<RpcLargestAccountsConfig>,
) -> RpcResponse<Vec<RpcAccountBalance>> { ) -> 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( new_response(
&bank, &bank,
bank.get_largest_accounts( bank.get_largest_accounts(NUM_LARGEST_ACCOUNTS, &addresses, address_filter)
NUM_LARGEST_ACCOUNTS, .into_iter()
&HashSet::new(), .map(|(address, lamports)| RpcAccountBalance {
AccountAddressFilter::Exclude, address: address.to_string(),
) lamports,
.into_iter() })
.map(|(address, lamports)| RpcAccountBalance { .collect(),
address: address.to_string(),
lamports,
})
.collect(),
) )
} }
@ -851,7 +844,7 @@ pub trait RpcSol {
fn get_largest_accounts( fn get_largest_accounts(
&self, &self,
meta: Self::Metadata, meta: Self::Metadata,
commitment: Option<CommitmentConfig>, config: Option<RpcLargestAccountsConfig>,
) -> RpcResponse<Vec<RpcAccountBalance>>; ) -> RpcResponse<Vec<RpcAccountBalance>>;
#[rpc(meta, name = "getSupply")] #[rpc(meta, name = "getSupply")]
@ -1276,13 +1269,13 @@ impl RpcSol for RpcSolImpl {
fn get_largest_accounts( fn get_largest_accounts(
&self, &self,
meta: Self::Metadata, meta: Self::Metadata,
commitment: Option<CommitmentConfig>, config: Option<RpcLargestAccountsConfig>,
) -> RpcResponse<Vec<RpcAccountBalance>> { ) -> RpcResponse<Vec<RpcAccountBalance>> {
debug!("get_largest_accounts rpc request received"); debug!("get_largest_accounts rpc request received");
meta.request_processor meta.request_processor
.read() .read()
.unwrap() .unwrap()
.get_largest_accounts(commitment) .get_largest_accounts(config)
} }
fn get_supply( fn get_supply(
@ -1637,6 +1630,7 @@ pub mod tests {
commitment::BlockCommitment, commitment::BlockCommitment,
contact_info::ContactInfo, contact_info::ContactInfo,
genesis_utils::{create_genesis_config, GenesisConfigInfo}, genesis_utils::{create_genesis_config, GenesisConfigInfo},
non_circulating_supply::non_circulating_accounts,
replay_stage::tests::create_test_transactions_and_populate_blockstore, replay_stage::tests::create_test_transactions_and_populate_blockstore,
}; };
use bincode::deserialize; use bincode::deserialize;
@ -1786,6 +1780,9 @@ pub mod tests {
let blockhash = bank.confirmed_last_blockhash().0; let blockhash = bank.confirmed_last_blockhash().0;
let tx = system_transaction::transfer(&alice, pubkey, 20, blockhash); let tx = system_transaction::transfer(&alice, pubkey, 20, blockhash);
bank.process_transaction(&tx).expect("process transaction"); 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 tx = system_transaction::transfer(&alice, pubkey, std::u64::MAX, blockhash);
let _ = bank.process_transaction(&tx); let _ = bank.process_transaction(&tx);
@ -1942,7 +1939,7 @@ pub mod tests {
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getTransactionCount"}}"#); let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getTransactionCount"}}"#);
let res = io.handle_request_sync(&req, meta); 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 = let expected: Response =
serde_json::from_str(&expected).expect("expected response deserialization"); serde_json::from_str(&expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response")) let result: Response = serde_json::from_str(&res.expect("actual response"))
@ -1990,6 +1987,31 @@ pub mod tests {
assert!(supply >= TEST_MINT_LAMPORTS); 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] #[test]
fn test_get_largest_accounts() { fn test_get_largest_accounts() {
let bob_pubkey = Pubkey::new_rand(); let bob_pubkey = Pubkey::new_rand();
@ -2002,7 +2024,7 @@ pub mod tests {
let largest_accounts: Vec<RpcAccountBalance> = let largest_accounts: Vec<RpcAccountBalance> =
serde_json::from_value(json["result"]["value"].clone()) serde_json::from_value(json["result"]["value"].clone())
.expect("actual response deserialization"); .expect("actual response deserialization");
assert_eq!(largest_accounts.len(), 18); assert_eq!(largest_accounts.len(), 19);
// Get Alice balance // Get Alice balance
let req = format!( let req = format!(
@ -2023,7 +2045,7 @@ pub mod tests {
r#"{{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["{}"]}}"#, r#"{{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["{}"]}}"#,
bob_pubkey 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 json: Value = serde_json::from_str(&res.unwrap()).unwrap();
let bob_balance: u64 = serde_json::from_value(json["result"]["value"].clone()) let bob_balance: u64 = serde_json::from_value(json["result"]["value"].clone())
.expect("actual response deserialization"); .expect("actual response deserialization");
@ -2031,6 +2053,26 @@ pub mod tests {
address: bob_pubkey.to_string(), address: bob_pubkey.to_string(),
lamports: bob_balance, 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] #[test]