Improve Rpc inflation tooling (#10309)

automerge
This commit is contained in:
Tyera Eulberg 2020-05-29 12:50:25 -06:00 committed by GitHub
parent 75924bd232
commit b563b49ed5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 217 additions and 58 deletions

1
Cargo.lock generated
View File

@ -3971,6 +3971,7 @@ dependencies = [
"solana-clap-utils",
"solana-client",
"solana-faucet",
"solana-genesis-programs",
"solana-ledger",
"solana-logger",
"solana-measure",

View File

@ -22,7 +22,6 @@ use solana_sdk::{
epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeRateGovernor},
hash::Hash,
inflation::Inflation,
pubkey::Pubkey,
signature::Signature,
signers::Signers,
@ -346,8 +345,12 @@ impl RpcClient {
})
}
pub fn get_inflation(&self) -> ClientResult<Inflation> {
self.send(RpcRequest::GetInflation, Value::Null)
pub fn get_inflation_governor(&self) -> ClientResult<RpcInflationGovernor> {
self.send(RpcRequest::GetInflationGovernor, Value::Null)
}
pub fn get_inflation_rate(&self) -> ClientResult<RpcInflationRate> {
self.send(RpcRequest::GetInflationRate, Value::Null)
}
pub fn get_version(&self) -> ClientResult<RpcVersionInfo> {

View File

@ -1,4 +1,4 @@
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::{clock::Epoch, commitment_config::CommitmentConfig};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
@ -26,3 +26,11 @@ pub struct RpcLargestAccountsConfig {
pub commitment: Option<CommitmentConfig>,
pub filter: Option<RpcLargestAccountsFilter>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcInflationConfig {
pub epoch: Option<Epoch>,
#[serde(flatten)]
pub commitment: Option<CommitmentConfig>,
}

View File

@ -21,7 +21,8 @@ pub enum RpcRequest {
GetFees,
GetGenesisHash,
GetIdentity,
GetInflation,
GetInflationGovernor,
GetInflationRate,
GetLargestAccounts,
GetLeaderSchedule,
GetMinimumBalanceForRentExemption,
@ -67,7 +68,8 @@ impl fmt::Display for RpcRequest {
RpcRequest::GetFees => "getFees",
RpcRequest::GetGenesisHash => "getGenesisHash",
RpcRequest::GetIdentity => "getIdentity",
RpcRequest::GetInflation => "getInflation",
RpcRequest::GetInflationGovernor => "getInflationGovernor",
RpcRequest::GetInflationRate => "getInflationRate",
RpcRequest::GetLargestAccounts => "getLargestAccounts",
RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption",
@ -146,10 +148,6 @@ mod tests {
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getEpochInfo");
let test_request = RpcRequest::GetInflation;
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getInflation");
let test_request = RpcRequest::GetRecentBlockhash;
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getRecentBlockhash");

View File

@ -3,6 +3,7 @@ use solana_sdk::{
account::Account,
clock::{Epoch, Slot},
fee_calculator::{FeeCalculator, FeeRateGovernor},
inflation::Inflation,
pubkey::Pubkey,
transaction::{Result, TransactionError},
};
@ -55,6 +56,37 @@ pub struct RpcFeeRateGovernor {
pub fee_rate_governor: FeeRateGovernor,
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcInflationGovernor {
pub initial: f64,
pub terminal: f64,
pub taper: f64,
pub foundation: f64,
pub foundation_term: f64,
}
impl From<Inflation> for RpcInflationGovernor {
fn from(inflation: Inflation) -> Self {
Self {
initial: inflation.initial,
terminal: inflation.terminal,
taper: inflation.taper,
foundation: inflation.foundation,
foundation_term: inflation.foundation_term,
}
}
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcInflationRate {
pub total: f64,
pub validator: f64,
pub foundation: f64,
pub epoch: Epoch,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcKeyedAccount {

View File

@ -21,6 +21,7 @@ byteorder = "1.3.4"
chrono = { version = "0.4.11", features = ["serde"] }
core_affinity = "0.5.10"
crossbeam-channel = "0.4"
ed25519-dalek = "=1.0.0-pre.3"
fs_extra = "1.1.0"
flate2 = "1.0"
indexmap = "1.3"
@ -47,7 +48,7 @@ solana-clap-utils = { path = "../clap-utils", version = "1.3.0" }
solana-client = { path = "../client", version = "1.3.0" }
solana-transaction-status = { path = "../transaction-status", version = "1.3.0" }
solana-faucet = { path = "../faucet", version = "1.3.0" }
ed25519-dalek = "=1.0.0-pre.3"
solana-genesis-programs = { path = "../genesis-programs", version = "1.3.0" }
solana-ledger = { path = "../ledger", version = "1.3.0" }
solana-logger = { path = "../logger", version = "1.3.0" }
solana-merkle-tree = { path = "../merkle-tree", version = "1.3.0" }

View File

@ -26,12 +26,11 @@ use solana_ledger::{
use solana_perf::packet::PACKET_DATA_SIZE;
use solana_runtime::{accounts::AccountAddressFilter, bank::Bank};
use solana_sdk::{
clock::{Slot, UnixTimestamp},
clock::{Epoch, Slot, UnixTimestamp},
commitment_config::{CommitmentConfig, CommitmentLevel},
epoch_info::EpochInfo,
epoch_schedule::EpochSchedule,
hash::Hash,
inflation::Inflation,
pubkey::Pubkey,
signature::Signature,
timing::slot_duration_from_slots_per_year,
@ -173,8 +172,27 @@ impl JsonRpcRequestProcessor {
.collect())
}
pub fn get_inflation(&self, commitment: Option<CommitmentConfig>) -> Result<Inflation> {
Ok(self.bank(commitment)?.inflation())
pub fn get_inflation_governor(
&self,
commitment: Option<CommitmentConfig>,
) -> Result<RpcInflationGovernor> {
Ok(self.bank(commitment)?.inflation().into())
}
pub fn get_inflation_rate(&self, epoch: Option<Epoch>) -> Result<RpcInflationRate> {
let bank = self.bank(None)?;
let operating_mode = bank.operating_mode();
let epoch = epoch.unwrap_or_else(|| bank.epoch());
let inflation = solana_genesis_programs::get_inflation_for_epoch(operating_mode, epoch);
let year =
(bank.epoch_schedule().get_last_slot_in_epoch(epoch)) as f64 / bank.slots_per_year();
Ok(RpcInflationRate {
total: inflation.total(year),
validator: inflation.validator(year),
foundation: inflation.foundation(year),
epoch,
})
}
pub fn get_epoch_schedule(&self) -> Result<EpochSchedule> {
@ -757,12 +775,19 @@ pub trait RpcSol {
commitment: Option<CommitmentConfig>,
) -> Result<u64>;
#[rpc(meta, name = "getInflation")]
fn get_inflation(
#[rpc(meta, name = "getInflationGovernor")]
fn get_inflation_governor(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<Inflation>;
) -> Result<RpcInflationGovernor>;
#[rpc(meta, name = "getInflationRate")]
fn get_inflation_rate(
&self,
meta: Self::Metadata,
epoch: Option<Epoch>,
) -> Result<RpcInflationRate>;
#[rpc(meta, name = "getEpochSchedule")]
fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule>;
@ -1022,16 +1047,28 @@ impl RpcSol for RpcSolImpl {
.get_program_accounts(&program_id, commitment)
}
fn get_inflation(
fn get_inflation_governor(
&self,
meta: Self::Metadata,
commitment: Option<CommitmentConfig>,
) -> Result<Inflation> {
debug!("get_inflation rpc request received");
) -> Result<RpcInflationGovernor> {
debug!("get_inflation_governor rpc request received");
meta.request_processor
.read()
.unwrap()
.get_inflation(commitment)
.get_inflation_governor(commitment)
}
fn get_inflation_rate(
&self,
meta: Self::Metadata,
epoch: Option<Epoch>,
) -> Result<RpcInflationRate> {
debug!("get_inflation_rate rpc request received");
meta.request_processor
.read()
.unwrap()
.get_inflation_rate(epoch)
}
fn get_epoch_schedule(&self, meta: Self::Metadata) -> Result<EpochSchedule> {
@ -2066,11 +2103,11 @@ pub mod tests {
let bob_pubkey = Pubkey::new_rand();
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getInflation"}"#;
let rep = io.handle_request_sync(&req, meta);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getInflationGovernor"}"#;
let rep = io.handle_request_sync(&req, meta.clone());
let res: Response = serde_json::from_str(&rep.expect("actual response"))
.expect("actual response deserialization");
let inflation: Inflation = if let Response::Single(res) = res {
let inflation_governor: RpcInflationGovernor = if let Response::Single(res) = res {
if let Output::Success(res) = res {
serde_json::from_value(res.result).unwrap()
} else {
@ -2079,7 +2116,57 @@ pub mod tests {
} else {
panic!("Expected single response");
};
assert_eq!(inflation, bank.inflation());
let expected_inflation_governor: RpcInflationGovernor = bank.inflation().into();
assert_eq!(inflation_governor, expected_inflation_governor);
let req = r#"{"jsonrpc":"2.0","id":1,"method":"getInflationRate"}"#; // Queries current epoch by default
let rep = io.handle_request_sync(&req, meta.clone());
let res: Response = serde_json::from_str(&rep.expect("actual response"))
.expect("actual response deserialization");
let inflation_rate: RpcInflationRate = 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");
};
let operating_mode = bank.operating_mode();
let inflation = solana_genesis_programs::get_inflation_for_epoch(operating_mode, 0);
let year = (bank.epoch_schedule().get_last_slot_in_epoch(0)) as f64 / bank.slots_per_year();
let expected_inflation_rate = RpcInflationRate {
total: inflation.total(year),
validator: inflation.validator(year),
foundation: inflation.foundation(year),
epoch: 0,
};
assert_eq!(inflation_rate, expected_inflation_rate);
let epoch = 40_000_000; // After default foundation term
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"getInflationRate","params":[{}]}}"#,
epoch
); // Queries current epoch by default
let rep = io.handle_request_sync(&req, meta);
let res: Response = serde_json::from_str(&rep.expect("actual response"))
.expect("actual response deserialization");
let inflation_rate: RpcInflationRate = 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");
};
let expected_inflation_rate = RpcInflationRate {
total: 0.015,
validator: 0.015,
foundation: 0.0,
epoch,
};
assert_eq!(inflation_rate, expected_inflation_rate);
}
#[test]

View File

@ -31,7 +31,8 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
* [getFirstAvailableBlock](jsonrpc-api.md#getfirstavailableblock)
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
* [getIdentity](jsonrpc-api.md#getidentity)
* [getInflation](jsonrpc-api.md#getinflation)
* [getInflationGovernor](jsonrpc-api.md#getinflationgovernor)
* [getInflationRate](jsonrpc-api.md#getinflationrate)
* [getLargestAccounts](jsonrpc-api.md#getlargestaccounts)
* [getLeaderSchedule](jsonrpc-api.md#getleaderschedule)
* [getMinimumBalanceForRentExemption](jsonrpc-api.md#getminimumbalanceforrentexemption)
@ -635,33 +636,59 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
{"jsonrpc":"2.0","result":{"identity": "2r1F4iWqVcb8M1DbAjQuFpebkQHY9hcVU4WuW2DJBppN"},"id":1}
```
### getInflation
### getInflationGovernor
Returns the inflation configuration of the cluster
Returns the current inflation governor
#### Parameters:
None
* `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
#### Results:
The result field will be an Inflation object with the following fields:
The result field will be a JSON object with the following fields:
* `initial: <f64>`, the initial inflation percentage from time 0
* `terminal: <f64>`, terminal inflation percentage
* `taper: <f64>`, rate per year at which inflation is lowered
* `foundation: <f64>`, percentage of total inflation allocated to the foundation
* `foundationTerm: <f64>`, duration of foundation pool inflation in years
* `storage: <f64>`, percentage of total inflation allocated to storage rewards
#### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getInflation"}' http://localhost:8899
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getInflationGovernor"}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":{"foundation":0.05,"foundationTerm":7.0,"initial":0.15,"storage":0.1,"taper":0.15,"terminal":0.015},"id":1}
{"jsonrpc":"2.0","result":{"foundation":0.05,"foundationTerm":7.0,"initial":0.15,"taper":0.15,"terminal":0.015},"id":1}
```
### getInflationRate
Returns the specific inflation values for a particular epoch
#### Parameters:
* `<u64>` - (optional) Epoch, default is the current epoch
#### Results:
The result field will be a JSON object with the following fields:
* `total: <f64>`, total inflation
* `validator: <f64>`, inflation allocated to validators
* `foundation: <f64>`, inflation allocated to the foundation
* `epoch: <f64>`, epoch for which these values are valid
#### Example:
```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getInflationRate"}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":{"epoch":100,"foundation":0.001,"total":0.149,"validator":0.148},"id":1}
```
### getLargestAccounts

View File

@ -16,26 +16,28 @@ use log::*;
use solana_runtime::bank::{Bank, EnteredEpochCallback};
pub fn get_inflation(operating_mode: OperatingMode, epoch: Epoch) -> Option<Inflation> {
let past_epoch_inflation = get_inflation_for_epoch(operating_mode, epoch.saturating_sub(1));
let epoch_inflation = get_inflation_for_epoch(operating_mode, epoch);
if epoch_inflation != past_epoch_inflation || epoch == 0 {
Some(epoch_inflation)
} else {
None
}
}
pub fn get_inflation_for_epoch(operating_mode: OperatingMode, epoch: Epoch) -> Inflation {
match operating_mode {
OperatingMode::Development => {
if epoch == 0 {
Some(Inflation::default())
} else {
None
}
}
OperatingMode::Development => Inflation::default(),
OperatingMode::Stable | OperatingMode::Preview => {
if epoch == 0 {
// No inflation at epoch 0
Some(Inflation::new_disabled())
} else if epoch == std::u64::MAX {
if epoch == std::u64::MAX {
// Inflation starts
//
// The epoch of std::u64::MAX - 1 is a placeholder and is expected to be reduced in
// The epoch of std::u64::MAX is a placeholder and is expected to be reduced in
// a future hard fork.
Some(Inflation::default())
Inflation::default()
} else {
None
// No inflation from epoch 0
Inflation::new_disabled()
}
}
}

View File

@ -1917,7 +1917,7 @@ impl Bank {
self.get_slots_in_epoch(self.first_normal_epoch())
}
fn operating_mode(&self) -> OperatingMode {
pub fn operating_mode(&self) -> OperatingMode {
// unwrap is safe; self.operating_mode is ensured to be Some() always...
// we only using Option here for ABI compatibility...
self.operating_mode.unwrap()
@ -6891,25 +6891,25 @@ mod tests {
if bank.slot == 0 {
assert_eq!(
bank.hash().to_string(),
"7MKHH6P7J5aQNN29Cr6aZQbEpQcXe8KTgchd4Suk9NCG"
"DX3Jk7ae6VdogRb73iC1zdyrYN5UzinLcSFES2FQx8dY"
);
}
if bank.slot == 32 {
assert_eq!(
bank.hash().to_string(),
"3AxuV6GGcoqRi6pksN6btNEmeJCTesLbjgA88QZt9a8Q"
"FqLpq1gmTdzEmdEPa2JttEFDqRtuKwkKFKuLuqNSiYwH"
);
}
if bank.slot == 64 {
assert_eq!(
bank.hash().to_string(),
"B32ZLAzeCW5FueeauiGYnujh8Efmxvpeac74W9JU68oB"
"rBbDCyHuCBWQrLY37zjj2zwsEnzNERWHwoH3W2NpRYe"
);
}
if bank.slot == 128 {
assert_eq!(
bank.hash().to_string(),
"A2tCz2EqryRZ7tHpw9H2918RZLCbqnSGzRWUqbnnESGz"
"E9DThiAPbheGeLWBDsts8uzuwF3bJQzDWh5uo8ovtYiy"
);
break;
}

View File

@ -18,7 +18,7 @@ pub struct Inflation {
/// Duration of foundation pool inflation, in years
pub foundation_term: f64,
/// Percentage of total inflation allocated to storage rewards
/// DEPRECATED, this field is currently unused
pub storage: f64,
}
@ -27,7 +27,7 @@ const DEFAULT_TERMINAL: f64 = 0.015;
const DEFAULT_TAPER: f64 = 0.15;
const DEFAULT_FOUNDATION: f64 = 0.05;
const DEFAULT_FOUNDATION_TERM: f64 = 7.0;
const DEFAULT_STORAGE: f64 = 0.10;
const DEFAULT_STORAGE: f64 = 0.0;
impl Default for Inflation {
fn default() -> Self {
@ -69,8 +69,8 @@ impl Inflation {
self.total(year) - self.storage(year) - self.foundation(year)
}
/// portion of total that goes to storage mining
pub fn storage(&self, year: f64) -> f64 {
/// DEPRECATED
fn storage(&self, year: f64) -> f64 {
self.total(year) * self.storage
}