Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
Rpc: introduce get_inflation_reward rpc call (#16278) (#16410)
Browse files Browse the repository at this point in the history
* feat: introduce get_inflation_reward rpc call

* fix: style suggestions

* fix: more style changes and match how other rpc functions are defined

* feat: get reward for a single epoch

* feat: default to the most recent epoch

* fix: don't factor out get_confirmed_block

* style: introduce from impl for RpcEncodingConfigWrapper

* style: bring commitment into variable

* feat: support multiple pubkeys for get_inflation_reward

* feat: add get_inflation_reward to rpc client

* feat: return rewards in order

* fix: rename pubkeys to addresses

* docs: introduce jsonrpc docs for get_inflation_reward

* style: early return in map (not sure which is more idiomatic)

* fix: call the rpc client function args addresses as well

* fix: style

* fix: filter out only addresses we care about

* style: make this more idiomatic

* fix: change rpc client epoch to optional and include some docs edits

* feat: filter out rent rewards in get_inflation_reward

* feat: add option epoch config param to get_inflation_reward

* feat: rpc client get_inflation_reward takes epoch instead of config and some filter staking and voting rewards

(cherry picked from commit e501fa5)

Co-authored-by: Josh <josh.hundley@gmail.com>
  • Loading branch information
mergify[bot] and oJshua authored Apr 7, 2021
1 parent f6780d7 commit a285792
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 9 deletions.
27 changes: 24 additions & 3 deletions client/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use {
mock_sender::{MockSender, Mocks},
rpc_config::RpcAccountInfoConfig,
rpc_config::{
RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig,
RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig, RpcEpochConfig,
RpcGetConfirmedSignaturesForAddress2Config, RpcLargestAccountsConfig,
RpcProgramAccountsConfig, RpcSendTransactionConfig, RpcSimulateTransactionConfig,
RpcStakeConfig, RpcTokenAccountsFilter,
RpcTokenAccountsFilter,
},
rpc_request::{RpcError, RpcRequest, RpcResponseErrorData, TokenAccountsFilter},
rpc_response::*,
Expand Down Expand Up @@ -436,7 +436,7 @@ impl RpcClient {
RpcRequest::GetStakeActivation,
json!([
stake_account.to_string(),
RpcStakeConfig {
RpcEpochConfig {
epoch,
commitment: Some(self.commitment_config),
}
Expand Down Expand Up @@ -764,6 +764,27 @@ impl RpcClient {
self.send(RpcRequest::GetInflationRate, Value::Null)
}

pub fn get_inflation_reward(
&self,
addresses: &[Pubkey],
epoch: Option<Epoch>,
) -> ClientResult<Vec<Option<RpcInflationReward>>> {
let addresses: Vec<_> = addresses
.iter()
.map(|address| address.to_string())
.collect();
self.send(
RpcRequest::GetInflationReward,
json!([
addresses,
RpcEpochConfig {
epoch,
commitment: Some(self.commitment_config),
}
]),
)
}

pub fn get_version(&self) -> ClientResult<RpcVersionInfo> {
self.send(RpcRequest::GetVersion, Value::Null)
}
Expand Down
8 changes: 7 additions & 1 deletion client/src/rpc_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub struct RpcLargestAccountsConfig {

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcStakeConfig {
pub struct RpcEpochConfig {
pub epoch: Option<Epoch>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
Expand Down Expand Up @@ -161,6 +161,12 @@ impl RpcConfirmedBlockConfig {
}
}

impl From<RpcConfirmedBlockConfig> for RpcEncodingConfigWrapper<RpcConfirmedBlockConfig> {
fn from(config: RpcConfirmedBlockConfig) -> Self {
RpcEncodingConfigWrapper::Current(Some(config))
}
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcConfirmedTransactionConfig {
Expand Down
2 changes: 2 additions & 0 deletions client/src/rpc_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub enum RpcRequest {
GetIdentity,
GetInflationGovernor,
GetInflationRate,
GetInflationReward,
GetLargestAccounts,
GetLeaderSchedule,
GetMaxRetransmitSlot,
Expand Down Expand Up @@ -91,6 +92,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetIdentity => "getIdentity",
RpcRequest::GetInflationGovernor => "getInflationGovernor",
RpcRequest::GetInflationRate => "getInflationRate",
RpcRequest::GetInflationReward => "getInflationReward",
RpcRequest::GetLargestAccounts => "getLargestAccounts",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetMaxRetransmitSlot => "getMaxRetransmitSlot",
Expand Down
9 changes: 9 additions & 0 deletions client/src/rpc_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,15 @@ pub struct RpcPerfSample {
pub sample_period_secs: u16,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcInflationReward {
pub epoch: Epoch,
pub effective_slot: Slot,
pub amount: u64, // lamports
pub post_balance: u64, // lamports
}

impl From<ConfirmedTransactionStatusWithSignature> for RpcConfirmedTransactionStatusWithSignature {
fn from(value: ConfirmedTransactionStatusWithSignature) -> Self {
let ConfirmedTransactionStatusWithSignature {
Expand Down
123 changes: 118 additions & 5 deletions core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ use solana_sdk::{
};
use solana_stake_program::stake_state::StakeState;
use solana_transaction_status::{
EncodedConfirmedTransaction, TransactionConfirmationStatus, TransactionStatus,
UiConfirmedBlock, UiTransactionEncoding,
EncodedConfirmedTransaction, Reward, RewardType, TransactionConfirmationStatus,
TransactionStatus, UiConfirmedBlock, UiTransactionEncoding,
};
use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
use spl_token_v2_0::{
Expand Down Expand Up @@ -382,6 +382,92 @@ impl JsonRpcRequestProcessor {
Ok(result)
}

pub fn get_inflation_reward(
&self,
addresses: Vec<Pubkey>,
config: Option<RpcEpochConfig>,
) -> Result<Vec<Option<RpcInflationReward>>> {
let config = config.unwrap_or_default();
let epoch_schedule = self.get_epoch_schedule();
let first_available_block = self.get_first_available_block();
let epoch = config.epoch.unwrap_or_else(|| {
epoch_schedule
.get_epoch(self.get_slot(config.commitment))
.saturating_sub(1)
});

// Rewards for this epoch are found in the first confirmed block of the next epoch
let first_slot_in_epoch = epoch_schedule.get_first_slot_in_epoch(epoch.saturating_add(1));
if first_slot_in_epoch < first_available_block {
if self.bigtable_ledger_storage.is_some() {
return Err(RpcCustomError::LongTermStorageSlotSkipped {
slot: first_slot_in_epoch,
}
.into());
} else {
return Err(RpcCustomError::BlockCleanedUp {
slot: first_slot_in_epoch,
first_available_block,
}
.into());
}
}

let first_confirmed_block_in_epoch = *self
.get_confirmed_blocks_with_limit(first_slot_in_epoch, 1, config.commitment)?
.get(0)
.ok_or(RpcCustomError::BlockNotAvailable {
slot: first_slot_in_epoch,
})?;

let first_confirmed_block = if let Ok(Some(first_confirmed_block)) = self
.get_confirmed_block(
first_confirmed_block_in_epoch,
Some(RpcConfirmedBlockConfig::rewards_only().into()),
) {
first_confirmed_block
} else {
return Err(RpcCustomError::BlockNotAvailable {
slot: first_confirmed_block_in_epoch,
}
.into());
};

let addresses: Vec<String> = addresses
.into_iter()
.map(|pubkey| pubkey.to_string())
.collect();

let reward_hash: HashMap<String, Reward> = first_confirmed_block
.rewards
.unwrap_or_default()
.into_iter()
.filter_map(|reward| match reward.reward_type? {
RewardType::Staking | RewardType::Voting => addresses
.contains(&reward.pubkey)
.then(|| (reward.clone().pubkey, reward)),
_ => None,
})
.collect();

let rewards = addresses
.iter()
.map(|address| {
if let Some(reward) = reward_hash.get(address) {
return Some(RpcInflationReward {
epoch,
effective_slot: first_confirmed_block_in_epoch,
amount: reward.lamports.abs() as u64,
post_balance: reward.post_balance,
});
}
None
})
.collect();

Ok(rewards)
}

pub fn get_inflation_governor(
&self,
commitment: Option<CommitmentConfig>,
Expand Down Expand Up @@ -1258,7 +1344,7 @@ impl JsonRpcRequestProcessor {
pub fn get_stake_activation(
&self,
pubkey: &Pubkey,
config: Option<RpcStakeConfig>,
config: Option<RpcEpochConfig>,
) -> Result<RpcStakeActivation> {
let config = config.unwrap_or_default();
let bank = self.bank(config.commitment);
Expand Down Expand Up @@ -2184,6 +2270,14 @@ pub mod rpc_full {
commitment: Option<CommitmentConfig>,
) -> Result<u64>;

#[rpc(meta, name = "getInflationReward")]
fn get_inflation_reward(
&self,
meta: Self::Metadata,
address_strs: Vec<String>,
config: Option<RpcEpochConfig>,
) -> Result<Vec<Option<RpcInflationReward>>>;

#[rpc(meta, name = "getInflationGovernor")]
fn get_inflation_governor(
&self,
Expand Down Expand Up @@ -2388,7 +2482,7 @@ pub mod rpc_full {
&self,
meta: Self::Metadata,
pubkey_str: String,
config: Option<RpcStakeConfig>,
config: Option<RpcEpochConfig>,
) -> Result<RpcStakeActivation>;

// SPL Token-specific RPC endpoints
Expand Down Expand Up @@ -3127,7 +3221,7 @@ pub mod rpc_full {
&self,
meta: Self::Metadata,
pubkey_str: String,
config: Option<RpcStakeConfig>,
config: Option<RpcEpochConfig>,
) -> Result<RpcStakeActivation> {
debug!(
"get_stake_activation rpc request received: {:?}",
Expand All @@ -3137,6 +3231,25 @@ pub mod rpc_full {
meta.get_stake_activation(&pubkey, config)
}

fn get_inflation_reward(
&self,
meta: Self::Metadata,
address_strs: Vec<String>,
config: Option<RpcEpochConfig>,
) -> Result<Vec<Option<RpcInflationReward>>> {
debug!(
"get_inflation_reward rpc request received: {:?}",
address_strs.len()
);

let mut addresses: Vec<Pubkey> = vec![];
for address_str in address_strs {
addresses.push(verify_pubkey(address_str)?);
}

meta.get_inflation_reward(addresses, config)
}

fn get_token_account_balance(
&self,
meta: Self::Metadata,
Expand Down
53 changes: 53 additions & 0 deletions docs/src/developing/clients/jsonrpc-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ gives a convenient interface for the RPC methods.
- [getIdentity](jsonrpc-api.md#getidentity)
- [getInflationGovernor](jsonrpc-api.md#getinflationgovernor)
- [getInflationRate](jsonrpc-api.md#getinflationrate)
- [getInflationReward](jsonrpc-api.md#getinflationreward)
- [getLargestAccounts](jsonrpc-api.md#getlargestaccounts)
- [getLeaderSchedule](jsonrpc-api.md#getleaderschedule)
- [getMaxRetransmitSlot](jsonrpc-api.md#getmaxretransmitslot)
Expand Down Expand Up @@ -1468,6 +1469,58 @@ Result:
{"jsonrpc":"2.0","result":{"epoch":100,"foundation":0.001,"total":0.149,"validator":0.148},"id":1}
```

### getInflationReward

Returns the inflation reward for a list of addresses for an epoch

#### Parameters:
- `<array>` - An array of addresses to query, as base-58 encoded strings
* `<object>` - (optional) Configuration object containing the following optional fields:
* (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
* (optional) `epoch: <u64>` - An epoch for which the reward occurs. If omitted, the previous epoch will be used

#### Results

The result field will be a JSON array with the following fields:

- `epoch: <u64>`, epoch
- `effective_slot: <u64>`, the slot in which the rewards are effective
- `amount: <u64>`, reward amount in lamports
- `post_balance: <u64>`, post balance of the account in lamports

#### Example

Request:
```bash
curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
{
"jsonrpc": "2.0",
"id": 1,
"method": "getInflationReward",
"params": [
["6dmNQ5jwLeLk5REvio1JcMshcbvkYMwy26sJ8pbkvStu", "BGsqMegLpV6n6Ve146sSX2dTjUMj3M92HnU8BbNRMhF2"], 2
]
}
'
```

Response:
```json
{
"jsonrpc": "2.0",
"result": [
{
"amount": 2500,
"effectiveSlot": 224,
"epoch": 2,
"postBalance": 499999442500
},
null
],
"id": 1
}
```

### getLargestAccounts

Returns the 20 largest accounts, by lamport balance (results may be cached up to two hours)
Expand Down

0 comments on commit a285792

Please sign in to comment.