Add circ/non-circ filter to getLargestAccounts (#10188)
This commit is contained in:
@ -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;
|
||||||
|
@ -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)]
|
||||||
|
@ -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",
|
||||||
|
100
core/src/rpc.rs
100
core/src/rpc.rs
@ -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,16 +272,24 @@ 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,
|
|
||||||
&HashSet::new(),
|
|
||||||
AccountAddressFilter::Exclude,
|
|
||||||
)
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(address, lamports)| RpcAccountBalance {
|
.map(|(address, lamports)| RpcAccountBalance {
|
||||||
address: address.to_string(),
|
address: address.to_string(),
|
||||||
@ -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]
|
||||||
|
Reference in New Issue
Block a user