Skip to content

Commit

Permalink
Split signature throughput tracking out of FeeCalculator (#8447)
Browse files Browse the repository at this point in the history
* SDK: Split new `FeeRateGovernor` out of `FeeCalculator`

Leaving `FeeCalculator` to *only* calculate transaction fees

* Replace `FeeCalculator` with `FeeRateGovernor` as appropriate

* Expose recent `FeeRateGovernor` to clients

* Move `burn()` back into `FeeCalculator`

Appease BPF tests

* Revert "Move `burn()` back into `FeeCalculator`"

This reverts commit f303562.

* Adjust BPF `Fee` sysvar test to reflect removal of `burn()` from `FeeCalculator`

* Make `FeeRateGovernor`'s `lamports_per_signature` private

* rebase artifacts

* fmt

* Drop 'Recent'

* Drop _with_commitment variant

* Use a more portable integer for `target_signatures_per_slot`

* Add docs for `getReeRateCalculator` JSON RPC method

* Don't return `lamports_per_signature` in `getFeeRateGovernor` JSONRPC reply
  • Loading branch information
t-nelson authored Feb 28, 2020
1 parent 7d27be2 commit 90bedd7
Show file tree
Hide file tree
Showing 22 changed files with 298 additions and 118 deletions.
10 changes: 5 additions & 5 deletions bench-tps/src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1059,8 +1059,8 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
// pay for the transaction fees in a new run.
let enough_lamports = 8 * lamports_per_account / 10;
if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports {
let (_blockhash, fee_calculator) = get_recent_blockhash(client.as_ref());
let max_fee = fee_calculator.max_lamports_per_signature;
let fee_rate_governor = client.get_fee_rate_governor().unwrap();
let max_fee = fee_rate_governor.max_lamports_per_signature;
let extra_fees = extra * max_fee;
let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
let mut total = lamports_per_account * total_keypairs + extra_fees;
Expand Down Expand Up @@ -1134,7 +1134,7 @@ mod tests {
use solana_runtime::bank::Bank;
use solana_runtime::bank_client::BankClient;
use solana_sdk::client::SyncClient;
use solana_sdk::fee_calculator::FeeCalculator;
use solana_sdk::fee_calculator::FeeRateGovernor;
use solana_sdk::genesis_config::create_genesis_config;

#[test]
Expand Down Expand Up @@ -1181,8 +1181,8 @@ mod tests {
#[test]
fn test_bench_tps_fund_keys_with_fees() {
let (mut genesis_config, id) = create_genesis_config(10_000);
let fee_calculator = FeeCalculator::new(11, 0);
genesis_config.fee_calculator = fee_calculator;
let fee_rate_governor = FeeRateGovernor::new(11, 0);
genesis_config.fee_rate_governor = fee_rate_governor;
let bank = Bank::new(&genesis_config);
let client = Arc::new(BankClient::new(bank));
let keypair_count = 20;
Expand Down
4 changes: 2 additions & 2 deletions bench-tps/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::{crate_description, crate_name, App, Arg, ArgMatches};
use solana_faucet::faucet::FAUCET_PORT;
use solana_sdk::fee_calculator::FeeCalculator;
use solana_sdk::fee_calculator::FeeRateGovernor;
use solana_sdk::signature::{read_keypair_file, Keypair};
use std::{net::SocketAddr, process::exit, time::Duration};

Expand Down Expand Up @@ -43,7 +43,7 @@ impl Default for Config {
client_ids_and_stake_file: String::new(),
write_to_client_file: false,
read_from_client_file: false,
target_lamports_per_signature: FeeCalculator::default().target_lamports_per_signature,
target_lamports_per_signature: FeeRateGovernor::default().target_lamports_per_signature,
multi_client: true,
use_move: false,
num_lamports_per_account: NUM_LAMPORTS_PER_ACCOUNT_DEFAULT,
Expand Down
4 changes: 2 additions & 2 deletions bench-tps/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate
use solana_bench_tps::cli;
use solana_core::gossip_service::{discover_cluster, get_client, get_multi_client};
use solana_genesis::Base64Account;
use solana_sdk::fee_calculator::FeeCalculator;
use solana_sdk::fee_calculator::FeeRateGovernor;
use solana_sdk::signature::{Keypair, Signer};
use solana_sdk::system_program;
use std::{collections::HashMap, fs::File, io::prelude::*, path::Path, process::exit, sync::Arc};
Expand Down Expand Up @@ -41,7 +41,7 @@ fn main() {
let (keypairs, _) = generate_keypairs(&id, keypair_count as u64);
let num_accounts = keypairs.len() as u64;
let max_fee =
FeeCalculator::new(*target_lamports_per_signature, 0).max_lamports_per_signature;
FeeRateGovernor::new(*target_lamports_per_signature, 0).max_lamports_per_signature;
let num_lamports_per_account = (num_accounts - 1 + NUM_SIGNATURES_FOR_TXS * max_fee)
/ num_accounts
+ num_lamports_per_account;
Expand Down
2 changes: 1 addition & 1 deletion cli/src/offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ mod tests {
fn test_blockhashspec_get_blockhash_fee_calc() {
let test_blockhash = hash(&[0u8]);
let rpc_blockhash = hash(&[1u8]);
let rpc_fee_calc = FeeCalculator::new(42, 42);
let rpc_fee_calc = FeeCalculator::new(42);
let get_recent_blockhash_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!((
Expand Down
6 changes: 5 additions & 1 deletion client/src/mock_rpc_client_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};
use serde_json::{Number, Value};
use solana_sdk::{
fee_calculator::FeeCalculator,
fee_calculator::{FeeCalculator, FeeRateGovernor},
instruction::InstructionError,
transaction::{self, TransactionError},
};
Expand Down Expand Up @@ -71,6 +71,10 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
serde_json::to_value(FeeCalculator::default()).unwrap(),
),
})?,
RpcRequest::GetFeeRateGovernor => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 },
value: serde_json::to_value(FeeRateGovernor::default()).unwrap(),
})?,
RpcRequest::GetSignatureStatus => {
let response: Option<transaction::Result<()>> = if self.url == "account_in_use" {
Some(Err(TransactionError::AccountInUse))
Expand Down
31 changes: 28 additions & 3 deletions client/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::{
rpc_request::RpcRequest,
rpc_response::{
Response, RpcAccount, RpcBlockhashFeeCalculator, RpcConfirmedBlock, RpcContactInfo,
RpcEpochInfo, RpcKeyedAccount, RpcLeaderSchedule, RpcResponse, RpcVersionInfo,
RpcVoteAccountStatus,
RpcEpochInfo, RpcFeeRateGovernor, RpcKeyedAccount, RpcLeaderSchedule, RpcResponse,
RpcVersionInfo, RpcVoteAccountStatus,
},
};
use bincode::serialize;
Expand All @@ -18,7 +18,7 @@ use solana_sdk::{
clock::{Slot, UnixTimestamp, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT},
commitment_config::CommitmentConfig,
epoch_schedule::EpochSchedule,
fee_calculator::FeeCalculator,
fee_calculator::{FeeCalculator, FeeRateGovernor},
hash::Hash,
inflation::Inflation,
pubkey::Pubkey,
Expand Down Expand Up @@ -804,6 +804,31 @@ impl RpcClient {
})
}

pub fn get_fee_rate_governor(&self) -> RpcResponse<FeeRateGovernor> {
let response = self
.client
.send(&RpcRequest::GetFeeRateGovernor, Value::Null, 0)
.map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("GetFeeRateGovernor request failure: {:?}", e),
)
})?;
let Response {
context,
value: RpcFeeRateGovernor { fee_rate_governor },
} = serde_json::from_value::<Response<RpcFeeRateGovernor>>(response).map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("GetFeeRateGovernor parse failure: {:?}", e),
)
})?;
Ok(Response {
context,
value: fee_rate_governor,
})
}

pub fn get_new_blockhash(&self, blockhash: &Hash) -> io::Result<(Hash, FeeCalculator)> {
let mut num_retries = 0;
let start = Instant::now();
Expand Down
6 changes: 6 additions & 0 deletions client/src/rpc_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub enum RpcRequest {
GetNumBlocksSinceSignatureConfirmation,
GetProgramAccounts,
GetRecentBlockhash,
GetFeeRateGovernor,
GetSignatureStatus,
GetSlot,
GetSlotLeader,
Expand Down Expand Up @@ -61,6 +62,7 @@ impl RpcRequest {
}
RpcRequest::GetProgramAccounts => "getProgramAccounts",
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
RpcRequest::GetSignatureStatus => "getSignatureStatus",
RpcRequest::GetSlot => "getSlot",
RpcRequest::GetSlotLeader => "getSlotLeader",
Expand Down Expand Up @@ -138,6 +140,10 @@ mod tests {
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getRecentBlockhash");

let test_request = RpcRequest::GetFeeRateGovernor;
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getFeeRateGovernor");

let test_request = RpcRequest::GetSlot;
let request = test_request.build_request_json(1, Value::Null);
assert_eq!(request["method"], "getSlot");
Expand Down
8 changes: 7 additions & 1 deletion client/src/rpc_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use jsonrpc_core::Result as JsonResult;
use solana_sdk::{
account::Account,
clock::{Epoch, Slot},
fee_calculator::FeeCalculator,
fee_calculator::{FeeCalculator, FeeRateGovernor},
message::MessageHeader,
pubkey::Pubkey,
transaction::{Result, Transaction},
Expand Down Expand Up @@ -152,6 +152,12 @@ pub struct RpcBlockhashFeeCalculator {
pub fee_calculator: FeeCalculator,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcFeeRateGovernor {
pub fee_rate_governor: FeeRateGovernor,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RpcKeyedAccount {
Expand Down
7 changes: 6 additions & 1 deletion client/src/thin_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use solana_sdk::{
client::{AsyncClient, Client, SyncClient},
clock::MAX_PROCESSING_AGE,
commitment_config::CommitmentConfig,
fee_calculator::FeeCalculator,
fee_calculator::{FeeCalculator, FeeRateGovernor},
hash::Hash,
instruction::Instruction,
message::Message,
Expand Down Expand Up @@ -445,6 +445,11 @@ impl SyncClient for ThinClient {
}
}

fn get_fee_rate_governor(&self) -> TransportResult<FeeRateGovernor> {
let fee_rate_governor = self.rpc_client().get_fee_rate_governor()?;
Ok(fee_rate_governor.value)
}

fn get_signature_status(
&self,
signature: &Signature,
Expand Down
54 changes: 50 additions & 4 deletions core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use jsonrpc_core::{Error, Metadata, Result};
use jsonrpc_derive::rpc;
use solana_client::rpc_response::{
Response, RpcAccount, RpcBlockCommitment, RpcBlockhashFeeCalculator, RpcConfirmedBlock,
RpcContactInfo, RpcEpochInfo, RpcKeyedAccount, RpcLeaderSchedule, RpcResponseContext,
RpcSignatureConfirmation, RpcStorageTurn, RpcTransactionEncoding, RpcVersionInfo,
RpcVoteAccountInfo, RpcVoteAccountStatus,
RpcContactInfo, RpcEpochInfo, RpcFeeRateGovernor, RpcKeyedAccount, RpcLeaderSchedule,
RpcResponseContext, RpcSignatureConfirmation, RpcStorageTurn, RpcTransactionEncoding,
RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus,
};
use solana_faucet::faucet::request_airdrop_transaction;
use solana_ledger::{
Expand Down Expand Up @@ -164,6 +164,17 @@ impl JsonRpcRequestProcessor {
)
}

fn get_fee_rate_governor(&self) -> RpcResponse<RpcFeeRateGovernor> {
let bank = &*self.bank(None);
let fee_rate_governor = bank.get_fee_rate_governor();
new_response(
bank,
RpcFeeRateGovernor {
fee_rate_governor: fee_rate_governor.clone(),
},
)
}

pub fn confirm_transaction(
&self,
signature: Result<Signature>,
Expand Down Expand Up @@ -491,6 +502,9 @@ pub trait RpcSol {
commitment: Option<CommitmentConfig>,
) -> RpcResponse<RpcBlockhashFeeCalculator>;

#[rpc(meta, name = "getFeeRateGovernor")]
fn get_fee_rate_governor(&self, meta: Self::Metadata) -> RpcResponse<RpcFeeRateGovernor>;

#[rpc(meta, name = "getSignatureStatus")]
fn get_signature_status(
&self,
Expand Down Expand Up @@ -813,6 +827,14 @@ impl RpcSol for RpcSolImpl {
.get_recent_blockhash(commitment)
}

fn get_fee_rate_governor(&self, meta: Self::Metadata) -> RpcResponse<RpcFeeRateGovernor> {
debug!("get_fee_rate_governor rpc request received");
meta.request_processor
.read()
.unwrap()
.get_fee_rate_governor()
}

fn get_signature_status(
&self,
meta: Self::Metadata,
Expand Down Expand Up @@ -1770,8 +1792,32 @@ pub mod tests {
"value":{
"blockhash": blockhash.to_string(),
"feeCalculator": {
"burnPercent": DEFAULT_BURN_PERCENT,
"lamportsPerSignature": 0,
}
}},
"id": 1
});
let expected: Response =
serde_json::from_value(expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
assert_eq!(expected, result);
}

#[test]
fn test_rpc_get_fee_rate_governor() {
let bob_pubkey = Pubkey::new_rand();
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);

let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getFeeRateGovernor"}}"#);
let res = io.handle_request_sync(&req, meta);
let expected = json!({
"jsonrpc": "2.0",
"result": {
"context":{"slot":0},
"value":{
"feeRateGovernor": {
"burnPercent": DEFAULT_BURN_PERCENT,
"maxLamportsPerSignature": 0,
"minLamportsPerSignature": 0,
"targetLamportsPerSignature": 0,
Expand Down
4 changes: 2 additions & 2 deletions core/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ impl TestValidator {

pub fn run_with_options(options: TestValidatorOptions) -> Self {
use crate::genesis_utils::{create_genesis_config_with_leader_ex, GenesisConfigInfo};
use solana_sdk::fee_calculator::FeeCalculator;
use solana_sdk::fee_calculator::FeeRateGovernor;

let TestValidatorOptions {
fees,
Expand All @@ -706,7 +706,7 @@ impl TestValidator {

genesis_config.rent.lamports_per_byte_year = 1;
genesis_config.rent.exemption_threshold = 1.0;
genesis_config.fee_calculator = FeeCalculator::new(fees, 0);
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0);

let (ledger_path, blockhash) = create_new_tmp_ledger!(&genesis_config);

Expand Down
29 changes: 29 additions & 0 deletions docs/src/apps/jsonrpc-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
* [getConfirmedBlocks](jsonrpc-api.md#getconfirmedblocks)
* [getEpochInfo](jsonrpc-api.md#getepochinfo)
* [getEpochSchedule](jsonrpc-api.md#getepochschedule)
* [getFeeRateGovernor](jsonrpc-api.md#getfeerategovernor)
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
* [getInflation](jsonrpc-api.md#getinflation)
* [getLeaderSchedule](jsonrpc-api.md#getleaderschedule)
Expand Down Expand Up @@ -403,6 +404,34 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
{"jsonrpc":"2.0","result":{"firstNormalEpoch":8,"firstNormalSlot":8160,"leaderScheduleSlotOffset":8192,"slotsPerEpoch":8192,"warmup":true},"id":1}
```

### getFeeRateGovernor

Returns the fee rate governor information from the root bank

#### Parameters:

None

#### Results:

The `result` field will be an `object` with the following fields:

* `burnPercent: <u8>`, Percentage of fees collected to be destroyed
* `maxLamportsPerSignature: <u64>`, Largest value `lamportsPerSignature` can attain for the next slot
* `minLamportsPerSignature: <u64>`, Smallest value `lamportsPerSignature` can attain for the next slot
* `targetLamportsPerSignature: <u64>`, Desired fee rate for the cluster
* `targetSignaturesPerSlot: <u64>`, Desired signature rate for the cluster

#### Example:

```bash
// Request
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getFeeRateGovernor"}' http://localhost:8899

// Result
{"jsonrpc":"2.0","result":{"context":{"slot":54},"value":{"feeRateGovernor":{"burnPercent":50,"maxLamportsPerSignature":100000,"minLamportsPerSignature":5000,"targetLamportsPerSignature":10000,"targetSignaturesPerSlot":20000}}},"id":1}
```

### getGenesisHash

Returns the genesis hash
Expand Down
Loading

0 comments on commit 90bedd7

Please sign in to comment.