GetLeaderSchedule can now return a schedule for arbitrary epochs

This commit is contained in:
Michael Vines 2019-12-17 16:26:31 -07:00
parent 629a4b5bf8
commit 434cde179f
4 changed files with 97 additions and 5 deletions

View File

@ -373,15 +373,16 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
### getLeaderSchedule
Returns the leader schedule for the current epoch
Returns the leader schedule for an epoch
#### Parameters:
* `slot` - (optional) Fetch the leader schedule for the epoch that corresponds to the provided slot. If unspecified, the leader schedule for the current epoch is fetch
* `object` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
#### Results:
The result field will be an array of leader public keys \(as base-58 encoded strings\) for each slot in the current epoch
The result field will be an array of leader public keys \(as base-58 encoded strings\) for each slot in the epoch
#### Example:

View File

@ -248,6 +248,39 @@ impl RpcClient {
})
}
pub fn get_leader_schedule(&self, slot: Option<Slot>) -> io::Result<Option<Vec<String>>> {
self.get_leader_schedule_with_commitment(slot, CommitmentConfig::default())
}
pub fn get_leader_schedule_with_commitment(
&self,
slot: Option<Slot>,
commitment_config: CommitmentConfig,
) -> io::Result<Option<Vec<String>>> {
let params = slot.map(|slot| json!(slot));
let response = self
.client
.send(
&RpcRequest::GetLeaderSchedule,
params,
0,
commitment_config.ok(),
)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
format!("GetLeaderSchedule request failure: {:?}", err),
)
})?;
serde_json::from_value(response).map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
format!("GetLeaderSchedule failure: {}", err),
)
})
}
pub fn get_epoch_schedule(&self) -> io::Result<EpochSchedule> {
let response = self
.client

View File

@ -121,6 +121,7 @@ pub enum RpcRequest {
GetEpochSchedule,
GetGenesisHash,
GetInflation,
GetLeaderSchedule,
GetNumBlocksSinceSignatureConfirmation,
GetProgramAccounts,
GetRecentBlockhash,
@ -161,6 +162,7 @@ impl RpcRequest {
RpcRequest::GetEpochSchedule => "getEpochSchedule",
RpcRequest::GetGenesisHash => "getGenesisHash",
RpcRequest::GetInflation => "getInflation",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetNumBlocksSinceSignatureConfirmation => {
"getNumBlocksSinceSignatureConfirmation"
}

View File

@ -419,7 +419,7 @@ pub trait RpcSol {
fn get_block_commitment(
&self,
meta: Self::Metadata,
block: u64,
block: Slot,
) -> Result<(Option<BlockCommitment>, u64)>;
#[rpc(meta, name = "getGenesisHash")]
@ -429,6 +429,7 @@ pub trait RpcSol {
fn get_leader_schedule(
&self,
meta: Self::Metadata,
slot: Option<Slot>,
commitment: Option<CommitmentConfig>,
) -> Result<Option<Vec<String>>>;
@ -679,8 +680,9 @@ impl RpcSol for RpcSolImpl {
) -> Result<RpcEpochInfo> {
let bank = meta.request_processor.read().unwrap().bank(commitment);
let epoch_schedule = bank.epoch_schedule();
let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(bank.slot());
let slot = bank.slot();
let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(slot);
Ok(RpcEpochInfo {
epoch,
slot_index,
@ -709,11 +711,14 @@ impl RpcSol for RpcSolImpl {
fn get_leader_schedule(
&self,
meta: Self::Metadata,
slot: Option<Slot>,
commitment: Option<CommitmentConfig>,
) -> Result<Option<Vec<String>>> {
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(bank.epoch(), &bank).map(
solana_ledger::leader_schedule_utils::leader_schedule(epoch, &bank).map(
|leader_schedule| {
leader_schedule
.get_slot_leaders()
@ -1374,6 +1379,57 @@ pub mod tests {
assert_eq!(epoch_schedule, *bank.epoch_schedule());
}
#[test]
fn test_rpc_get_leader_schedule() {
let bob_pubkey = Pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
for req in [
r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [0]}"#,
r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule"}"#,
]
.iter()
{
let rep = io.handle_request_sync(&req, meta.clone());
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 {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
} else {
panic!("Expected success for {}", req);
}
} else {
panic!("Expected single response");
};
assert_eq!(
schedule.unwrap().len(),
solana_ledger::leader_schedule_utils::leader_schedule(bank.epoch(), &bank)
.unwrap()
.get_slot_leaders()
.len()
);
}
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [42424242]}"#;
let rep = io.handle_request_sync(&req, meta);
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 {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
} else {
panic!("Expected success");
}
} else {
panic!("Expected single response");
};
assert_eq!(schedule, None);
}
#[test]
fn test_rpc_get_account_info() {
let bob_pubkey = Pubkey::new_rand();