diff --git a/cli/src/vote.rs b/cli/src/vote.rs index 5f742ff40..d1bf263a6 100644 --- a/cli/src/vote.rs +++ b/cli/src/vote.rs @@ -10,8 +10,8 @@ use crate::{ use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand}; use solana_client::rpc_client::RpcClient; use solana_sdk::{ - account::Account, epoch_schedule::EpochSchedule, pubkey::Pubkey, signature::KeypairUtil, - system_instruction::SystemError, sysvar, transaction::Transaction, + account::Account, pubkey::Pubkey, signature::KeypairUtil, system_instruction::SystemError, + transaction::Transaction, }; use solana_vote_api::{ vote_instruction::{self, VoteError}, @@ -301,22 +301,6 @@ pub fn process_vote_authorize( log_instruction_custom_error::(result) } -fn get_epoch_schedule(rpc_client: &RpcClient) -> Result> { - let epoch_schedule_account = rpc_client.get_account(&sysvar::epoch_schedule::id())?; - - if epoch_schedule_account.owner != sysvar::id() { - return Err(CliError::RpcRequestError(format!( - "{:?} is not an epoch_schedule account", - sysvar::epoch_schedule::id() - )) - .into()); - } - - let epoch_schedule = EpochSchedule::deserialize(&epoch_schedule_account)?; - - Ok(epoch_schedule) -} - fn get_vote_account( rpc_client: &RpcClient, vote_account_pubkey: &Pubkey, @@ -346,7 +330,7 @@ pub fn process_show_vote_account( ) -> ProcessResult { let (vote_account, vote_state) = get_vote_account(rpc_client, vote_account_pubkey)?; - let epoch_schedule = get_epoch_schedule(rpc_client)?; + let epoch_schedule = rpc_client.get_epoch_schedule()?; println!( "account balance: {}", @@ -401,7 +385,7 @@ pub fn process_uptime( ) -> ProcessResult { let (_vote_account, vote_state) = get_vote_account(rpc_client, vote_account_pubkey)?; - let epoch_schedule = get_epoch_schedule(rpc_client)?; + let epoch_schedule = rpc_client.get_epoch_schedule()?; println!("Node id: {}", vote_state.node_pubkey); println!("Authorized voter: {}", vote_state.authorized_voter); diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index dfa246607..dc1cb02e0 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -9,6 +9,7 @@ use serde_json::{json, Value}; use solana_sdk::{ account::Account, clock::{Slot, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT}, + epoch_schedule::EpochSchedule, fee_calculator::FeeCalculator, hash::Hash, inflation::Inflation, @@ -138,6 +139,25 @@ impl RpcClient { }) } + pub fn get_epoch_schedule(&self) -> io::Result { + let response = self + .client + .send(&RpcRequest::GetEpochSchedule, None, 0) + .map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("GetEpochSchedule request failure: {:?}", err), + ) + })?; + + serde_json::from_value(response).map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("GetEpochSchedule parse failure: {}", err), + ) + }) + } + pub fn get_inflation(&self) -> io::Result { let response = self .client diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index 3a3b04d19..95658220e 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -58,6 +58,7 @@ pub enum RpcRequest { GetBalance, GetClusterNodes, GetEpochInfo, + GetEpochSchedule, GetGenesisBlockhash, GetInflation, GetNumBlocksSinceSignatureConfirmation, @@ -91,6 +92,7 @@ impl RpcRequest { RpcRequest::GetBalance => "getBalance", RpcRequest::GetClusterNodes => "getClusterNodes", RpcRequest::GetEpochInfo => "getEpochInfo", + RpcRequest::GetEpochSchedule => "getEpochSchedule", RpcRequest::GetGenesisBlockhash => "getGenesisBlockhash", RpcRequest::GetInflation => "getInflation", RpcRequest::GetNumBlocksSinceSignatureConfirmation => { diff --git a/core/src/rpc.rs b/core/src/rpc.rs index b0a44d82c..434ccb1f4 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -18,6 +18,7 @@ use solana_ledger::bank_forks::BankForks; use solana_runtime::bank::Bank; use solana_sdk::{ account::Account, + epoch_schedule::EpochSchedule, fee_calculator::FeeCalculator, hash::Hash, inflation::Inflation, @@ -101,6 +102,10 @@ impl JsonRpcRequestProcessor { Ok(self.bank().inflation()) } + pub fn get_epoch_schedule(&self) -> Result { + Ok(*self.bank().epoch_schedule()) + } + pub fn get_balance(&self, pubkey: &Pubkey) -> u64 { self.bank().get_balance(&pubkey) } @@ -289,6 +294,9 @@ pub trait RpcSol { #[rpc(meta, name = "getInflation")] fn get_inflation(&self, _: Self::Metadata) -> Result; + #[rpc(meta, name = "getEpochSchedule")] + fn get_epoch_schedule(&self, _: Self::Metadata) -> Result; + #[rpc(meta, name = "getBalance")] fn get_balance(&self, _: Self::Metadata, _: String) -> Result; @@ -439,6 +447,16 @@ impl RpcSol for RpcSolImpl { .unwrap()) } + fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result { + debug!("get_epoch_schedule rpc request received"); + Ok(meta + .request_processor + .read() + .unwrap() + .get_epoch_schedule() + .unwrap()) + } + fn get_balance(&self, meta: Self::Metadata, id: String) -> Result { debug!("get_balance rpc request received: {:?}", id); let pubkey = verify_pubkey(id)?; @@ -991,6 +1009,28 @@ pub mod tests { assert_eq!(inflation, bank.inflation()); } + #[test] + fn test_rpc_get_epoch_schedule() { + let bob_pubkey = Pubkey::new_rand(); + let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey); + + let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getEpochSchedule"}}"#); + let rep = io.handle_request_sync(&req, meta); + let res: Response = serde_json::from_str(&rep.expect("actual response")) + .expect("actual response deserialization"); + + let epoch_schedule: EpochSchedule = if let Response::Single(res) = res { + if let Output::Success(res) = res { + serde_json::from_value(res.result).unwrap() + } else { + panic!("Expected success"); + } + } else { + panic!("Expected single response"); + }; + assert_eq!(epoch_schedule, *bank.epoch_schedule()); + } + #[test] fn test_rpc_get_account_info() { let bob_pubkey = Pubkey::new_rand();