Speed up getLeaderSchedule RPC call by reducing pubkey duplication

This commit is contained in:
Michael Vines
2019-12-18 12:42:58 -07:00
parent 6a9005645a
commit bd22b641b3
4 changed files with 36 additions and 18 deletions

View File

@ -12,8 +12,8 @@ use bincode::serialize;
use jsonrpc_core::{Error, Metadata, Result};
use jsonrpc_derive::rpc;
use solana_client::rpc_request::{
Response, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcResponseContext, RpcVersionInfo,
RpcVoteAccountInfo, RpcVoteAccountStatus,
Response, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcLeaderSchedule,
RpcResponseContext, RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus,
};
use solana_faucet::faucet::request_airdrop_transaction;
use solana_ledger::{bank_forks::BankForks, blocktree::Blocktree};
@ -431,7 +431,7 @@ pub trait RpcSol {
meta: Self::Metadata,
slot: Option<Slot>,
commitment: Option<CommitmentConfig>,
) -> Result<Option<Vec<String>>>;
) -> Result<Option<RpcLeaderSchedule>>;
#[rpc(meta, name = "getRecentBlockhash")]
fn get_recent_blockhash(
@ -713,18 +713,23 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata,
slot: Option<Slot>,
commitment: Option<CommitmentConfig>,
) -> Result<Option<Vec<String>>> {
) -> Result<Option<RpcLeaderSchedule>> {
let bank = meta.request_processor.read().unwrap().bank(commitment);
let slot = slot.unwrap_or_else(|| bank.slot());
let epoch = bank.epoch_schedule().get_epoch(slot);
Ok(
solana_ledger::leader_schedule_utils::leader_schedule(epoch, &bank).map(
|leader_schedule| {
leader_schedule
.get_slot_leaders()
.iter()
.map(|pubkey| pubkey.to_string())
.collect()
let mut map = HashMap::new();
for (slot_index, pubkey) in
leader_schedule.get_slot_leaders().iter().enumerate()
{
let pubkey = pubkey.to_string();
map.entry(pubkey).or_insert_with(|| vec![]).push(slot_index);
}
map
},
),
)
@ -1394,7 +1399,7 @@ pub mod tests {
let res: Response = serde_json::from_str(&rep.expect("actual response"))
.expect("actual response deserialization");
let schedule: Option<Vec<String>> = if let Response::Single(res) = res {
let schedule: Option<RpcLeaderSchedule> = if let Response::Single(res) = res {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
} else {
@ -1403,9 +1408,14 @@ pub mod tests {
} else {
panic!("Expected single response");
};
let schedule = schedule.expect("leader schedule");
let bob_schedule = schedule
.get(&bank.collector_id().to_string())
.expect("leader not in the leader schedule");
assert_eq!(
schedule.unwrap().len(),
bob_schedule.len(),
solana_ledger::leader_schedule_utils::leader_schedule(bank.epoch(), &bank)
.unwrap()
.get_slot_leaders()
@ -1418,7 +1428,7 @@ pub mod tests {
let res: Response = serde_json::from_str(&rep.expect("actual response"))
.expect("actual response deserialization");
let schedule: Option<Vec<String>> = if let Response::Single(res) = res {
let schedule: Option<RpcLeaderSchedule> = if let Response::Single(res) = res {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
} else {