Add getEpochInfo() and getLeaderSchedule() RPC methods (#5189)
* Add getLeaderSchedule() RPC method * Add getEpochInfo() RPC method * Add JSON RPC docs
This commit is contained in:
@ -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
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user