Add getEpochInfo() and getLeaderSchedule() RPC methods (#5189)

* Add getLeaderSchedule() RPC method

* Add getEpochInfo() RPC method

* Add JSON RPC docs
This commit is contained in:
Michael Vines
2019-07-19 07:31:18 -07:00
committed by GitHub
parent 83aa609540
commit adfb8ff2a1
4 changed files with 99 additions and 4 deletions

View File

@ -25,6 +25,8 @@ Methods
* [getAccountInfo](#getaccountinfo) * [getAccountInfo](#getaccountinfo)
* [getBalance](#getbalance) * [getBalance](#getbalance)
* [getClusterNodes](#getclusternodes) * [getClusterNodes](#getclusternodes)
* [getEpochInfo](#getepochinfo)
* [getLeaderSchedule](#getleaderschedule)
* [getProgramAccounts](#getprogramaccounts) * [getProgramAccounts](#getprogramaccounts)
* [getRecentBlockhash](#getrecentblockhash) * [getRecentBlockhash](#getrecentblockhash)
* [getSignatureStatus](#getsignaturestatus) * [getSignatureStatus](#getsignaturestatus)
@ -172,6 +174,50 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "
--- ---
### getEpochInfo
Returns information about the current epoch
##### Parameters:
None
##### Results:
The result field will be an object with the following fields:
* `epoch`, the current epoch
* `slotIndex`, the current slot relative to the start of the current epoch
* `slotsInEpoch`, the number of slots in this epoch
##### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getEpochInfo"}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":{"epoch":3,"slotIndex":126,"slotsInEpoch":256},"id":1}
```
---
### getLeaderSchedule
Returns the leader schedule for the current epoch
##### Parameters:
None
##### Results:
The result field will be an array of leader public keys (as base-58 encoded
strings) for each slot in the current epoch
##### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getLeaderSchedule"}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":[...],"id":1}
```
---
### getProgramAccounts ### getProgramAccounts
Returns all accounts owned by the provided program Pubkey Returns all accounts owned by the provided program Pubkey

View File

@ -29,6 +29,10 @@ impl LeaderSchedule {
.collect(); .collect();
Self { slot_leaders } Self { slot_leaders }
} }
pub(crate) fn get_slot_leaders(&self) -> &[Pubkey] {
&self.slot_leaders
}
} }
impl Index<u64> for LeaderSchedule { impl Index<u64> for LeaderSchedule {

View File

@ -5,16 +5,16 @@ use solana_sdk::pubkey::Pubkey;
use solana_sdk::timing::NUM_CONSECUTIVE_LEADER_SLOTS; use solana_sdk::timing::NUM_CONSECUTIVE_LEADER_SLOTS;
/// Return the leader schedule for the given epoch. /// Return the leader schedule for the given epoch.
pub fn leader_schedule(epoch_height: u64, bank: &Bank) -> Option<LeaderSchedule> { pub fn leader_schedule(epoch: u64, bank: &Bank) -> Option<LeaderSchedule> {
staking_utils::staked_nodes_at_epoch(bank, epoch_height).map(|stakes| { staking_utils::staked_nodes_at_epoch(bank, epoch).map(|stakes| {
let mut seed = [0u8; 32]; let mut seed = [0u8; 32];
seed[0..8].copy_from_slice(&epoch_height.to_le_bytes()); seed[0..8].copy_from_slice(&epoch.to_le_bytes());
let mut stakes: Vec<_> = stakes.into_iter().collect(); let mut stakes: Vec<_> = stakes.into_iter().collect();
sort_stakes(&mut stakes); sort_stakes(&mut stakes);
LeaderSchedule::new( LeaderSchedule::new(
&stakes, &stakes,
seed, seed,
bank.get_slots_in_epoch(epoch_height), bank.get_slots_in_epoch(epoch),
NUM_CONSECUTIVE_LEADER_SLOTS, NUM_CONSECUTIVE_LEADER_SLOTS,
) )
}) })

View File

@ -220,6 +220,19 @@ pub struct RpcVoteAccountInfo {
pub commission: u8, pub commission: u8,
} }
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcEpochInfo {
/// The current epoch
pub epoch: u64,
/// The number of slots in this epoch
pub slots_in_epoch: u64,
/// The current slot, relative to the start of the current epoch
pub slot_index: u64,
}
#[rpc(server)] #[rpc(server)]
pub trait RpcSol { pub trait RpcSol {
type Metadata; type Metadata;
@ -239,6 +252,12 @@ pub trait RpcSol {
#[rpc(meta, name = "getClusterNodes")] #[rpc(meta, name = "getClusterNodes")]
fn get_cluster_nodes(&self, _: Self::Metadata) -> Result<Vec<RpcContactInfo>>; fn get_cluster_nodes(&self, _: Self::Metadata) -> Result<Vec<RpcContactInfo>>;
#[rpc(meta, name = "getEpochInfo")]
fn get_epoch_info(&self, _: Self::Metadata) -> Result<RpcEpochInfo>;
#[rpc(meta, name = "getLeaderSchedule")]
fn get_leader_schedule(&self, _: Self::Metadata) -> Result<Option<Vec<String>>>;
#[rpc(meta, name = "getRecentBlockhash")] #[rpc(meta, name = "getRecentBlockhash")]
fn get_recent_blockhash(&self, _: Self::Metadata) -> Result<(String, FeeCalculator)>; fn get_recent_blockhash(&self, _: Self::Metadata) -> Result<(String, FeeCalculator)>;
@ -369,6 +388,32 @@ impl RpcSol for RpcSolImpl {
.collect()) .collect())
} }
fn get_epoch_info(&self, meta: Self::Metadata) -> Result<RpcEpochInfo> {
let bank = meta.request_processor.read().unwrap().bank();
let epoch_schedule = bank.epoch_schedule();
let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(bank.slot());
Ok(RpcEpochInfo {
epoch,
slots_in_epoch: epoch_schedule.get_slots_in_epoch(epoch),
slot_index,
})
}
fn get_leader_schedule(&self, meta: Self::Metadata) -> Result<Option<Vec<String>>> {
let bank = meta.request_processor.read().unwrap().bank();
Ok(
crate::leader_schedule_utils::leader_schedule(bank.epoch(), &bank).map(
|leader_schedule| {
leader_schedule
.get_slot_leaders()
.iter()
.map(|pubkey| pubkey.to_string())
.collect()
},
),
)
}
fn get_recent_blockhash(&self, meta: Self::Metadata) -> Result<(String, FeeCalculator)> { fn get_recent_blockhash(&self, meta: Self::Metadata) -> Result<(String, FeeCalculator)> {
debug!("get_recent_blockhash rpc request received"); debug!("get_recent_blockhash rpc request received");
Ok(meta Ok(meta