From 8d105042eac1376764676f2499c61bf95915fa71 Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Fri, 16 Aug 2019 17:02:19 -0600 Subject: [PATCH] Update getEpochVoteAccounts to getVoteAccounts (#5543) * Rework getEpochVoteAccounts into getVoteAccounts * Update client apis * Update docs * Review comments --- book/src/jsonrpc-api.md | 53 +++++++++++++++-------------- book/src/validator-monitor.md | 4 +-- client/src/rpc_request.rs | 4 +-- core/src/rpc.rs | 64 +++++++++++++++++++++++++---------- 4 files changed, 79 insertions(+), 46 deletions(-) diff --git a/book/src/jsonrpc-api.md b/book/src/jsonrpc-api.md index 2b83cf7ed8..d89db87f31 100644 --- a/book/src/jsonrpc-api.md +++ b/book/src/jsonrpc-api.md @@ -26,7 +26,6 @@ Methods * [getBalance](#getbalance) * [getClusterNodes](#getclusternodes) * [getEpochInfo](#getepochinfo) -* [getEpochVoteAccounts](#getepochvoteaccounts) * [getLeaderSchedule](#getleaderschedule) * [getProgramAccounts](#getprogramaccounts) * [getRecentBlockhash](#getrecentblockhash) @@ -40,6 +39,7 @@ Methods * [getTransactionCount](#gettransactioncount) * [getTotalSupply](#gettotalsupply) * [getVersion](#getversion) +* [getVoteAccounts](#getvoteaccounts) * [requestAirdrop](#requestairdrop) * [sendTransaction](#sendtransaction) * [startSubscriptionChannel](#startsubscriptionchannel) @@ -199,30 +199,6 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m --- -### getEpochVoteAccounts -Returns the account info and associated stake for all the voting accounts in the current epoch. - -##### Parameters: -None - -##### Results: -The result field will be an array of JSON objects, each with the following sub fields: -* `votePubkey` - Vote account public key, as base-58 encoded string -* `nodePubkey` - Node public key, as base-58 encoded string -* `stake` - the stake, in lamports, delegated to this vote account -* `commission`, a 32-bit integer used as a fraction (commission/MAX_U32) for rewards payout - -##### Example: -```bash -// Request -curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getEpochVoteAccounts"}' http://localhost:8899 - -// Result -{"jsonrpc":"2.0","result":[{"commission":0,"nodePubkey":"Et2RaZJdJRTzTkodUwiHr4H6sLkVmijBFv8tkd7oSSFY","stake":42,"votePubkey":"B4CdWq3NBSoH2wYsVE1CaZSWPo2ZtopE4SJipQhZ3srF"}],"id":1} -``` - ---- - ### getLeaderSchedule Returns the leader schedule for the current epoch @@ -498,6 +474,33 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m --- +### getVoteAccounts +Returns the account info and associated stake for all the voting accounts in the current bank. + +##### Parameters: +None + +##### Results: +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` - Vote account public key, as base-58 encoded string +* `nodePubkey` - Node public key, as base-58 encoded string +* `activatedStake` - the stake, in lamports, delegated to this vote account and active in this epoch +* `epochVoteAccount` - bool, whether the vote account is staked for this epoch +* `commission`, an 8-bit integer used as a fraction (commission/MAX_U8) for rewards payout +* `lastVote` - Most recent slot voted on by this vote account + +##### Example: +```bash +// Request +curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getVoteAccounts"}' http://localhost:8899 + +// Result +{"jsonrpc":"2.0","result":{"current":[{"commission":0,"epochVoteAccount":true,"nodePubkey":"B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD","lastVote":147,"activatedStake":42,"votePubkey":"3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw"}],"delinquent":[{"commission":127,"epochVoteAccount":false,"nodePubkey":"6ZPxeQaDo4bkZLRsdNrCzchNQr5LN9QMc9sipXv9Kw8f","lastVote":0,"activatedStake":0,"votePubkey":"CmgCk4aMS7KW1SHX3s9K5tBJ6Yng2LBaC8MFov4wx9sm"}]},"id":1} +``` + +--- + ### requestAirdrop Requests an airdrop of lamports to a Pubkey diff --git a/book/src/validator-monitor.md b/book/src/validator-monitor.md index 7b55eb43e1..dd4d894968 100644 --- a/book/src/validator-monitor.md +++ b/book/src/validator-monitor.md @@ -68,8 +68,8 @@ cluster, as well as the health of the cluster: ```bash # Similar to solana-gossip, you should see your validator in the list of cluster nodes $ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getClusterNodes"}' http://testnet.solana.com:8899 -# If your validator is properly staked and voting, it should appear in the list of epoch vote accounts -$ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getEpochVoteAccounts"}' http://testnet.solana.com:8899 +# If your validator is properly voting, it should appear in the list of `current` vote accounts. If staked, `stake` should be > 0 +$ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getVoteAccounts"}' http://testnet.solana.com:8899 # Returns the current leader schedule $ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getLeaderSchedule"}' http://testnet.solana.com:8899 # Returns info about the current epoch. slotIndex should progress on subsequent calls. diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index f39cec5a27..c1748803c9 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -9,7 +9,6 @@ pub enum RpcRequest { GetAccountInfo, GetBalance, GetClusterNodes, - GetEpochVoteAccounts, GetNumBlocksSinceSignatureConfirmation, GetProgramAccounts, GetRecentBlockhash, @@ -22,6 +21,7 @@ pub enum RpcRequest { GetStoragePubkeysForSlot, GetTransactionCount, GetVersion, + GetVoteAccounts, RegisterNode, RequestAirdrop, SendTransaction, @@ -38,7 +38,6 @@ impl RpcRequest { RpcRequest::GetAccountInfo => "getAccountInfo", RpcRequest::GetBalance => "getBalance", RpcRequest::GetClusterNodes => "getClusterNodes", - RpcRequest::GetEpochVoteAccounts => "getEpochVoteAccounts", RpcRequest::GetNumBlocksSinceSignatureConfirmation => { "getNumBlocksSinceSignatureConfirmation" } @@ -53,6 +52,7 @@ impl RpcRequest { RpcRequest::GetStoragePubkeysForSlot => "getStoragePubkeysForSlot", RpcRequest::GetTransactionCount => "getTransactionCount", RpcRequest::GetVersion => "getVersion", + RpcRequest::GetVoteAccounts => "getVoteAccounts", RpcRequest::RegisterNode => "registerNode", RpcRequest::RequestAirdrop => "requestAirdrop", RpcRequest::SendTransaction => "sendTransaction", diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 49e490bbb6..ff48ea85ec 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -16,7 +16,7 @@ use solana_sdk::fee_calculator::FeeCalculator; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::Signature; use solana_sdk::transaction::{self, Transaction}; -use solana_vote_api::vote_state::VoteState; +use solana_vote_api::vote_state::{VoteState, MAX_LOCKOUT_HISTORY}; use std::net::{SocketAddr, UdpSocket}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, RwLock}; @@ -122,22 +122,43 @@ impl JsonRpcRequestProcessor { Ok(self.bank().capitalization()) } - fn get_epoch_vote_accounts(&self) -> Result> { + fn get_vote_accounts(&self) -> Result { let bank = self.bank(); - Ok(bank + let vote_accounts = bank.vote_accounts(); + let epoch_vote_accounts = bank .epoch_vote_accounts(bank.get_epoch_and_slot_index(bank.slot()).0) - .ok_or_else(Error::invalid_request)? + .ok_or_else(Error::invalid_request)?; + let (current_vote_accounts, delinquent_vote_accounts): ( + Vec, + Vec, + ) = vote_accounts .iter() - .map(|(pubkey, (stake, account))| { - let vote_state = VoteState::from(account).unwrap_or_default(); + .map(|(pubkey, (activated_stake, account))| { + let vote_state = VoteState::from(&account).unwrap_or_default(); + let last_vote = if let Some(vote) = vote_state.votes.iter().last() { + vote.slot + } else { + 0 + }; + let epoch_vote_account = epoch_vote_accounts + .iter() + .any(|(epoch_vote_pubkey, _)| epoch_vote_pubkey == pubkey); RpcVoteAccountInfo { - vote_pubkey: (*pubkey).to_string(), + vote_pubkey: (pubkey).to_string(), node_pubkey: vote_state.node_pubkey.to_string(), - stake: *stake, + activated_stake: *activated_stake, commission: vote_state.commission, + epoch_vote_account, + last_vote, } }) - .collect::>()) + .partition(|vote_account_info| { + vote_account_info.last_vote >= bank.slot() - MAX_LOCKOUT_HISTORY as u64 + }); + Ok(RpcVoteAccountStatus { + current: current_vote_accounts, + delinquent: delinquent_vote_accounts, + }) } fn get_storage_turn_rate(&self) -> Result { @@ -204,6 +225,12 @@ pub struct RpcContactInfo { /// JSON RPC port pub rpc: Option, } +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RpcVoteAccountStatus { + pub current: Vec, + pub delinquent: Vec, +} #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] @@ -215,10 +242,16 @@ pub struct RpcVoteAccountInfo { pub node_pubkey: String, /// The current stake, in lamports, delegated to this vote account - pub stake: u64, + pub activated_stake: u64, /// An 8-bit integer used as a fraction (commission/MAX_U8) for rewards payout pub commission: u8, + + /// Whether this account is staked for the current epoch + pub epoch_vote_account: bool, + + /// Most recent slot voted on by this vote account + pub last_vote: u64, } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -294,8 +327,8 @@ pub trait RpcSol { #[rpc(meta, name = "getSlotLeader")] fn get_slot_leader(&self, _: Self::Metadata) -> Result; - #[rpc(meta, name = "getEpochVoteAccounts")] - fn get_epoch_vote_accounts(&self, _: Self::Metadata) -> Result>; + #[rpc(meta, name = "getVoteAccounts")] + fn get_vote_accounts(&self, _: Self::Metadata) -> Result; #[rpc(meta, name = "getStorageTurnRate")] fn get_storage_turn_rate(&self, _: Self::Metadata) -> Result; @@ -581,11 +614,8 @@ impl RpcSol for RpcSolImpl { meta.request_processor.read().unwrap().get_slot_leader() } - fn get_epoch_vote_accounts(&self, meta: Self::Metadata) -> Result> { - meta.request_processor - .read() - .unwrap() - .get_epoch_vote_accounts() + fn get_vote_accounts(&self, meta: Self::Metadata) -> Result { + meta.request_processor.read().unwrap().get_vote_accounts() } fn get_storage_turn_rate(&self, meta: Self::Metadata) -> Result {