From 90d586a4f801c14541ddfd0d5a671b22a72338b8 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 3 Oct 2020 02:00:49 +0000 Subject: [PATCH] `solana stakes` now employs server-side filtering if only one vote account is provided (#12657) (cherry picked from commit 9abaf6ec1d5643ea636200c90afc29270812af49) Co-authored-by: Michael Vines --- cli/src/cluster_query.rs | 49 +++++++++++++++++++++++++++++++++++----- client/src/rpc_client.rs | 23 ++++++++++++++----- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index ad449f496db147..551e85563f24f6 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -18,7 +18,11 @@ use solana_client::{ client_error::ClientErrorKind, pubsub_client::PubsubClient, rpc_client::{GetConfirmedSignaturesForAddress2Config, RpcClient}, - rpc_config::{RpcLargestAccountsConfig, RpcLargestAccountsFilter}, + rpc_config::{ + RpcAccountInfoConfig, RpcLargestAccountsConfig, RpcLargestAccountsFilter, + RpcProgramAccountsConfig, + }, + rpc_filter, rpc_response::SlotInfo, }; use solana_remote_wallet::remote_wallet::RemoteWalletManager; @@ -1276,17 +1280,50 @@ pub fn process_show_stakes( let progress_bar = new_spinner_progress_bar(); progress_bar.set_message("Fetching stake accounts..."); - let all_stake_accounts = rpc_client.get_program_accounts(&solana_stake_program::id())?; + + let mut program_accounts_config = RpcProgramAccountsConfig { + filters: None, + account_config: RpcAccountInfoConfig { + encoding: Some(solana_account_decoder::UiAccountEncoding::Base64), + ..RpcAccountInfoConfig::default() + }, + }; + + if let Some(vote_account_pubkeys) = vote_account_pubkeys { + // Use server-side filtering if only one vote account is provided + if vote_account_pubkeys.len() == 1 { + program_accounts_config.filters = Some(vec![ + // Filter by `StakeState::Stake(_, _)` + rpc_filter::RpcFilterType::Memcmp(rpc_filter::Memcmp { + offset: 0, + bytes: rpc_filter::MemcmpEncodedBytes::Binary( + bs58::encode([2, 0, 0, 0]).into_string(), + ), + encoding: Some(rpc_filter::MemcmpEncoding::Binary), + }), + // Filter by `Delegation::voter_pubkey`, which begins at byte offset 124 + rpc_filter::RpcFilterType::Memcmp(rpc_filter::Memcmp { + offset: 124, + bytes: rpc_filter::MemcmpEncodedBytes::Binary( + vote_account_pubkeys[0].to_string(), + ), + encoding: Some(rpc_filter::MemcmpEncoding::Binary), + }), + ]); + } + } + let all_stake_accounts = rpc_client + .get_program_accounts_with_config(&solana_stake_program::id(), program_accounts_config)?; let stake_history_account = rpc_client.get_account(&stake_history::id())?; - progress_bar.finish_and_clear(); let clock_account = rpc_client.get_account(&sysvar::clock::id())?; + let clock: Clock = Sysvar::from_account(&clock_account).ok_or_else(|| { + CliError::RpcRequestError("Failed to deserialize clock sysvar".to_string()) + })?; + progress_bar.finish_and_clear(); let stake_history = StakeHistory::from_account(&stake_history_account).ok_or_else(|| { CliError::RpcRequestError("Failed to deserialize stake history".to_string()) })?; - let clock: Clock = Sysvar::from_account(&clock_account).ok_or_else(|| { - CliError::RpcRequestError("Failed to deserialize clock sysvar".to_string()) - })?; let mut stake_accounts: Vec = vec![]; for (stake_pubkey, stake_account) in all_stake_accounts { diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 1712cb3228b27f..1b31f8238e2c64 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -5,7 +5,7 @@ use crate::{ rpc_config::RpcAccountInfoConfig, rpc_config::{ RpcGetConfirmedSignaturesForAddress2Config, RpcLargestAccountsConfig, - RpcSendTransactionConfig, RpcTokenAccountsFilter, + RpcProgramAccountsConfig, RpcSendTransactionConfig, RpcTokenAccountsFilter, }, rpc_request::{RpcError, RpcRequest, TokenAccountsFilter}, rpc_response::*, @@ -602,12 +602,23 @@ impl RpcClient { } pub fn get_program_accounts(&self, pubkey: &Pubkey) -> ClientResult> { - let config = RpcAccountInfoConfig { - encoding: Some(UiAccountEncoding::Base64), - commitment: None, - data_slice: None, - }; + self.get_program_accounts_with_config( + pubkey, + RpcProgramAccountsConfig { + filters: None, + account_config: RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64), + ..RpcAccountInfoConfig::default() + }, + }, + ) + } + pub fn get_program_accounts_with_config( + &self, + pubkey: &Pubkey, + config: RpcProgramAccountsConfig, + ) -> ClientResult> { let accounts: Vec = self.send( RpcRequest::GetProgramAccounts, json!([pubkey.to_string(), config]),