Speed up getLeaderSchedule RPC call by reducing pubkey duplication
This commit is contained in:
parent
6a9005645a
commit
bd22b641b3
|
@ -384,7 +384,9 @@ Returns the leader schedule for an epoch
|
||||||
|
|
||||||
#### Results:
|
#### Results:
|
||||||
|
|
||||||
The result field will be an array of leader public keys \(as base-58 encoded strings\) for each slot in the epoch
|
The result field will be a dictionary of leader public keys \(as base-58 encoded
|
||||||
|
strings\) and their corresponding leader slot indices as values (indices are to
|
||||||
|
the first slot in the requested epoch)
|
||||||
|
|
||||||
#### Example:
|
#### Example:
|
||||||
|
|
||||||
|
@ -393,7 +395,7 @@ The result field will be an array of leader public keys \(as base-58 encoded str
|
||||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getLeaderSchedule"}' http://localhost:8899
|
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getLeaderSchedule"}' http://localhost:8899
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
{"jsonrpc":"2.0","result":[...],"id":1}
|
{"jsonrpc":"2.0","result":{"4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63]},"id":1}
|
||||||
```
|
```
|
||||||
|
|
||||||
### getMinimumBalanceForRentExemption
|
### getMinimumBalanceForRentExemption
|
||||||
|
|
|
@ -4,7 +4,10 @@ use crate::{
|
||||||
generic_rpc_client_request::GenericRpcClientRequest,
|
generic_rpc_client_request::GenericRpcClientRequest,
|
||||||
mock_rpc_client_request::MockRpcClientRequest,
|
mock_rpc_client_request::MockRpcClientRequest,
|
||||||
rpc_client_request::RpcClientRequest,
|
rpc_client_request::RpcClientRequest,
|
||||||
rpc_request::{RpcContactInfo, RpcEpochInfo, RpcRequest, RpcVersionInfo, RpcVoteAccountStatus},
|
rpc_request::{
|
||||||
|
RpcContactInfo, RpcEpochInfo, RpcLeaderSchedule, RpcRequest, RpcVersionInfo,
|
||||||
|
RpcVoteAccountStatus,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
@ -248,7 +251,7 @@ impl RpcClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_leader_schedule(&self, slot: Option<Slot>) -> io::Result<Option<Vec<String>>> {
|
pub fn get_leader_schedule(&self, slot: Option<Slot>) -> io::Result<Option<RpcLeaderSchedule>> {
|
||||||
self.get_leader_schedule_with_commitment(slot, CommitmentConfig::default())
|
self.get_leader_schedule_with_commitment(slot, CommitmentConfig::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +259,7 @@ impl RpcClient {
|
||||||
&self,
|
&self,
|
||||||
slot: Option<Slot>,
|
slot: Option<Slot>,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
) -> io::Result<Option<Vec<String>>> {
|
) -> io::Result<Option<RpcLeaderSchedule>> {
|
||||||
let params = slot.map(|slot| json!(slot));
|
let params = slot.map(|slot| json!(slot));
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
|
|
|
@ -6,7 +6,7 @@ use solana_sdk::{
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
transaction::{Result, Transaction},
|
transaction::{Result, Transaction},
|
||||||
};
|
};
|
||||||
use std::{error, fmt, io, net::SocketAddr};
|
use std::{collections::HashMap, error, fmt, io, net::SocketAddr};
|
||||||
|
|
||||||
pub type RpcResponseIn<T> = JsonResult<Response<T>>;
|
pub type RpcResponseIn<T> = JsonResult<Response<T>>;
|
||||||
pub type RpcResponse<T> = io::Result<Response<T>>;
|
pub type RpcResponse<T> = io::Result<Response<T>>;
|
||||||
|
@ -52,6 +52,9 @@ pub struct RpcContactInfo {
|
||||||
pub rpc: Option<SocketAddr>,
|
pub rpc: Option<SocketAddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Map of leader base58 identity pubkeys to the slot indices relative to the first epoch slot
|
||||||
|
pub type RpcLeaderSchedule = HashMap<String, Vec<usize>>;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RpcEpochInfo {
|
pub struct RpcEpochInfo {
|
||||||
|
|
|
@ -12,8 +12,8 @@ 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_request::{
|
use solana_client::rpc_request::{
|
||||||
Response, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcResponseContext, RpcVersionInfo,
|
Response, RpcConfirmedBlock, RpcContactInfo, RpcEpochInfo, RpcLeaderSchedule,
|
||||||
RpcVoteAccountInfo, RpcVoteAccountStatus,
|
RpcResponseContext, RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus,
|
||||||
};
|
};
|
||||||
use solana_faucet::faucet::request_airdrop_transaction;
|
use solana_faucet::faucet::request_airdrop_transaction;
|
||||||
use solana_ledger::{bank_forks::BankForks, blocktree::Blocktree};
|
use solana_ledger::{bank_forks::BankForks, blocktree::Blocktree};
|
||||||
|
@ -431,7 +431,7 @@ pub trait RpcSol {
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
slot: Option<Slot>,
|
slot: Option<Slot>,
|
||||||
commitment: Option<CommitmentConfig>,
|
commitment: Option<CommitmentConfig>,
|
||||||
) -> Result<Option<Vec<String>>>;
|
) -> Result<Option<RpcLeaderSchedule>>;
|
||||||
|
|
||||||
#[rpc(meta, name = "getRecentBlockhash")]
|
#[rpc(meta, name = "getRecentBlockhash")]
|
||||||
fn get_recent_blockhash(
|
fn get_recent_blockhash(
|
||||||
|
@ -713,18 +713,23 @@ impl RpcSol for RpcSolImpl {
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
slot: Option<Slot>,
|
slot: Option<Slot>,
|
||||||
commitment: Option<CommitmentConfig>,
|
commitment: Option<CommitmentConfig>,
|
||||||
) -> Result<Option<Vec<String>>> {
|
) -> Result<Option<RpcLeaderSchedule>> {
|
||||||
let bank = meta.request_processor.read().unwrap().bank(commitment);
|
let bank = meta.request_processor.read().unwrap().bank(commitment);
|
||||||
let slot = slot.unwrap_or_else(|| bank.slot());
|
let slot = slot.unwrap_or_else(|| bank.slot());
|
||||||
let epoch = bank.epoch_schedule().get_epoch(slot);
|
let epoch = bank.epoch_schedule().get_epoch(slot);
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
solana_ledger::leader_schedule_utils::leader_schedule(epoch, &bank).map(
|
solana_ledger::leader_schedule_utils::leader_schedule(epoch, &bank).map(
|
||||||
|leader_schedule| {
|
|leader_schedule| {
|
||||||
leader_schedule
|
let mut map = HashMap::new();
|
||||||
.get_slot_leaders()
|
|
||||||
.iter()
|
for (slot_index, pubkey) in
|
||||||
.map(|pubkey| pubkey.to_string())
|
leader_schedule.get_slot_leaders().iter().enumerate()
|
||||||
.collect()
|
{
|
||||||
|
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"))
|
let res: Response = serde_json::from_str(&rep.expect("actual response"))
|
||||||
.expect("actual response deserialization");
|
.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 {
|
if let Output::Success(res) = res {
|
||||||
serde_json::from_value(res.result).unwrap()
|
serde_json::from_value(res.result).unwrap()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1403,9 +1408,14 @@ pub mod tests {
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected single response");
|
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!(
|
assert_eq!(
|
||||||
schedule.unwrap().len(),
|
bob_schedule.len(),
|
||||||
solana_ledger::leader_schedule_utils::leader_schedule(bank.epoch(), &bank)
|
solana_ledger::leader_schedule_utils::leader_schedule(bank.epoch(), &bank)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_slot_leaders()
|
.get_slot_leaders()
|
||||||
|
@ -1418,7 +1428,7 @@ pub mod tests {
|
||||||
let res: Response = serde_json::from_str(&rep.expect("actual response"))
|
let res: Response = serde_json::from_str(&rep.expect("actual response"))
|
||||||
.expect("actual response deserialization");
|
.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 {
|
if let Output::Success(res) = res {
|
||||||
serde_json::from_value(res.result).unwrap()
|
serde_json::from_value(res.result).unwrap()
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue