getLeaderSchedule now supports filtered results based on validator identity
This commit is contained in:
parent
3f92abedd5
commit
6004c0abf5
|
@ -9,11 +9,7 @@ use {
|
|||
http_sender::HttpSender,
|
||||
mock_sender::{MockSender, Mocks},
|
||||
rpc_config::RpcAccountInfoConfig,
|
||||
rpc_config::{
|
||||
RpcBlockConfig, RpcEpochConfig, RpcLargestAccountsConfig, RpcProgramAccountsConfig,
|
||||
RpcRequestAirdropConfig, RpcSendTransactionConfig, RpcSignaturesForAddressConfig,
|
||||
RpcSimulateTransactionConfig, RpcTokenAccountsFilter, RpcTransactionConfig,
|
||||
},
|
||||
rpc_config::*,
|
||||
rpc_request::{RpcError, RpcRequest, RpcResponseErrorData, TokenAccountsFilter},
|
||||
rpc_response::*,
|
||||
rpc_sender::RpcSender,
|
||||
|
@ -880,7 +876,7 @@ impl RpcClient {
|
|||
&self,
|
||||
slot: Option<Slot>,
|
||||
) -> ClientResult<Option<RpcLeaderSchedule>> {
|
||||
self.get_leader_schedule_with_commitment(slot, self.commitment_config)
|
||||
self.get_leader_schedule_with_config(slot, RpcLeaderScheduleConfig::default())
|
||||
}
|
||||
|
||||
pub fn get_leader_schedule_with_commitment(
|
||||
|
@ -890,10 +886,24 @@ impl RpcClient {
|
|||
) -> ClientResult<Option<RpcLeaderSchedule>> {
|
||||
self.send(
|
||||
RpcRequest::GetLeaderSchedule,
|
||||
json!([slot, self.maybe_map_commitment(commitment_config)?]),
|
||||
json!([
|
||||
slot,
|
||||
RpcLeaderScheduleConfig {
|
||||
commitment: Some(self.maybe_map_commitment(commitment_config)?),
|
||||
..RpcLeaderScheduleConfig::default()
|
||||
}
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_leader_schedule_with_config(
|
||||
&self,
|
||||
slot: Option<Slot>,
|
||||
config: RpcLeaderScheduleConfig,
|
||||
) -> ClientResult<Option<RpcLeaderSchedule>> {
|
||||
self.send(RpcRequest::GetLeaderSchedule, json!([slot, config]))
|
||||
}
|
||||
|
||||
pub fn get_epoch_schedule(&self) -> ClientResult<EpochSchedule> {
|
||||
self.send(RpcRequest::GetEpochSchedule, Value::Null)
|
||||
}
|
||||
|
|
|
@ -41,6 +41,14 @@ pub struct RpcRequestAirdropConfig {
|
|||
pub commitment: Option<CommitmentConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcLeaderScheduleConfig {
|
||||
pub identity: Option<String>, // validator identity, as a base-58 encoded string
|
||||
#[serde(flatten)]
|
||||
pub commitment: Option<CommitmentConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum RpcLargestAccountsFilter {
|
||||
|
|
|
@ -254,10 +254,10 @@ pub struct RpcVoteAccountStatus {
|
|||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcVoteAccountInfo {
|
||||
/// Vote account pubkey as base-58 encoded string
|
||||
/// Vote account address, as base-58 encoded string
|
||||
pub vote_pubkey: String,
|
||||
|
||||
/// The pubkey of the node that votes using this account
|
||||
/// The validator identity, as base-58 encoded string
|
||||
pub node_pubkey: String,
|
||||
|
||||
/// The current stake, in lamports, delegated to this vote account
|
||||
|
|
|
@ -2110,7 +2110,7 @@ pub mod rpc_minimal {
|
|||
&self,
|
||||
meta: Self::Metadata,
|
||||
slot: Option<Slot>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
config: Option<RpcLeaderScheduleConfig>,
|
||||
) -> Result<Option<RpcLeaderSchedule>>;
|
||||
}
|
||||
|
||||
|
@ -2215,9 +2215,15 @@ pub mod rpc_minimal {
|
|||
&self,
|
||||
meta: Self::Metadata,
|
||||
slot: Option<Slot>,
|
||||
commitment: Option<CommitmentConfig>,
|
||||
config: Option<RpcLeaderScheduleConfig>,
|
||||
) -> Result<Option<RpcLeaderSchedule>> {
|
||||
let bank = meta.bank(commitment);
|
||||
let config = config.unwrap_or_default();
|
||||
|
||||
if let Some(ref identity) = config.identity {
|
||||
let _ = verify_pubkey(identity)?;
|
||||
}
|
||||
|
||||
let bank = meta.bank(config.commitment);
|
||||
let slot = slot.unwrap_or_else(|| bank.slot());
|
||||
let epoch = bank.epoch_schedule().get_epoch(slot);
|
||||
|
||||
|
@ -2227,9 +2233,14 @@ pub mod rpc_minimal {
|
|||
.leader_schedule_cache
|
||||
.get_epoch_leader_schedule(epoch)
|
||||
.map(|leader_schedule| {
|
||||
solana_ledger::leader_schedule_utils::leader_schedule_by_identity(
|
||||
leader_schedule.get_slot_leaders().iter().enumerate(),
|
||||
)
|
||||
let mut schedule_by_identity =
|
||||
solana_ledger::leader_schedule_utils::leader_schedule_by_identity(
|
||||
leader_schedule.get_slot_leaders().iter().enumerate(),
|
||||
);
|
||||
if let Some(identity) = config.identity {
|
||||
schedule_by_identity.retain(|k, _| *k == identity);
|
||||
}
|
||||
schedule_by_identity
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -4235,6 +4246,10 @@ pub mod tests {
|
|||
for req in [
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [0]}"#,
|
||||
r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule"}"#,
|
||||
&format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [null, {{ "identity": "{}" }}]}}"#,
|
||||
bank.collector_id().to_string()
|
||||
),
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
|
@ -4267,7 +4282,7 @@ pub mod tests {
|
|||
}
|
||||
|
||||
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [42424242]}"#;
|
||||
let rep = io.handle_request_sync(&req, meta);
|
||||
let rep = io.handle_request_sync(&req, meta.clone());
|
||||
let res: Response = serde_json::from_str(&rep.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
|
||||
|
@ -4281,6 +4296,27 @@ pub mod tests {
|
|||
panic!("Expected single response");
|
||||
};
|
||||
assert_eq!(schedule, None);
|
||||
|
||||
// `bob` is not in the leader schedule, look for an empty response
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getLeaderSchedule", "params": [null, {{ "identity": "{}"}}]}}"#,
|
||||
bob_pubkey
|
||||
);
|
||||
|
||||
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<RpcLeaderSchedule> = 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, Some(HashMap::default()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1366,14 +1366,17 @@ Returns the leader schedule for an epoch
|
|||
|
||||
#### Parameters:
|
||||
|
||||
- `<u64>` - (optional) Fetch the leader schedule for the epoch that corresponds to the provided slot. If unspecified, the leader schedule for the current epoch is fetched
|
||||
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
- `<u64>` - (optional) Fetch the leader schedule for the epoch that corresponds to the provided slot.
|
||||
If unspecified, the leader schedule for the current epoch is fetched
|
||||
- `<object>` - (optional) Configuration object containing the following field:
|
||||
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
- (optional) `identity: <string>` - Only return results for this validator identity (base-58 encoded)
|
||||
|
||||
#### Results:
|
||||
|
||||
- `<null>` - if requested epoch is not found
|
||||
- `<object>` - otherwise, the result field will be a dictionary of leader public keys
|
||||
\(as base-58 encoded strings\) and their corresponding leader slot indices as values
|
||||
- `<object>` - otherwise, the result field will be a dictionary of validator identities,
|
||||
as base-58 encoded strings, and their corresponding leader slot indices as values
|
||||
(indices are relative to the first slot in the requested epoch)
|
||||
|
||||
#### Example:
|
||||
|
@ -1396,6 +1399,36 @@ Result:
|
|||
}
|
||||
```
|
||||
|
||||
#### Example:
|
||||
|
||||
Request:
|
||||
```bash
|
||||
curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "getLeaderSchedule",
|
||||
"params": [
|
||||
null,
|
||||
{
|
||||
"identity": "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F"
|
||||
}
|
||||
]
|
||||
}
|
||||
'
|
||||
```
|
||||
|
||||
Result:
|
||||
```json
|
||||
{
|
||||
"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
|
||||
}
|
||||
```
|
||||
|
||||
### getMaxRetransmitSlot
|
||||
|
||||
Get the max slot seen from retransmit stage.
|
||||
|
@ -2820,8 +2853,8 @@ Returns the account info and associated stake for all the voting accounts in the
|
|||
|
||||
The result field will be a JSON object of `current` and `delinquent` accounts, each containing an array of JSON objects with the following sub fields:
|
||||
|
||||
- `votePubkey: <string>` - Vote account public key, as base-58 encoded string
|
||||
- `nodePubkey: <string>` - Node public key, as base-58 encoded string
|
||||
- `votePubkey: <string>` - Vote account address, as base-58 encoded string
|
||||
- `nodePubkey: <string>` - Validator identity, as base-58 encoded string
|
||||
- `activatedStake: <u64>` - the stake, in lamports, delegated to this vote account and active in this epoch
|
||||
- `epochVoteAccount: <bool>` - bool, whether the vote account is staked for this epoch
|
||||
- `commission: <number>`, percentage (0-100) of rewards payout owed to the vote account
|
||||
|
|
|
@ -16,7 +16,10 @@ use {
|
|||
},
|
||||
keypair::SKIP_SEED_PHRASE_VALIDATION_ARG,
|
||||
},
|
||||
solana_client::{rpc_client::RpcClient, rpc_request::MAX_MULTIPLE_ACCOUNTS},
|
||||
solana_client::{
|
||||
rpc_client::RpcClient, rpc_config::RpcLeaderScheduleConfig,
|
||||
rpc_request::MAX_MULTIPLE_ACCOUNTS,
|
||||
},
|
||||
solana_core::ledger_cleanup_service::{
|
||||
DEFAULT_MAX_LEDGER_SHREDS, DEFAULT_MIN_MAX_LEDGER_SHREDS,
|
||||
},
|
||||
|
@ -154,7 +157,13 @@ fn wait_for_restart_window(
|
|||
));
|
||||
let first_slot_in_epoch = epoch_info.absolute_slot - epoch_info.slot_index;
|
||||
leader_schedule = rpc_client
|
||||
.get_leader_schedule(Some(first_slot_in_epoch))?
|
||||
.get_leader_schedule_with_config(
|
||||
Some(first_slot_in_epoch),
|
||||
RpcLeaderScheduleConfig {
|
||||
identity: Some(identity.to_string()),
|
||||
..RpcLeaderScheduleConfig::default()
|
||||
},
|
||||
)?
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"Unable to get leader schedule from slot {}",
|
||||
|
|
Loading…
Reference in New Issue