Split signature throughput tracking out of FeeCalculator
(#8447)
* 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 f3035624307196722b62ff8b74c12cfcc13b1941. * 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
This commit is contained in:
@ -1059,8 +1059,8 @@ pub fn generate_and_fund_keypairs<T: 'static + Client + Send + Sync>(
|
|||||||
// pay for the transaction fees in a new run.
|
// pay for the transaction fees in a new run.
|
||||||
let enough_lamports = 8 * lamports_per_account / 10;
|
let enough_lamports = 8 * lamports_per_account / 10;
|
||||||
if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports {
|
if first_keypair_balance < enough_lamports || last_keypair_balance < enough_lamports {
|
||||||
let (_blockhash, fee_calculator) = get_recent_blockhash(client.as_ref());
|
let fee_rate_governor = client.get_fee_rate_governor().unwrap();
|
||||||
let max_fee = fee_calculator.max_lamports_per_signature;
|
let max_fee = fee_rate_governor.max_lamports_per_signature;
|
||||||
let extra_fees = extra * max_fee;
|
let extra_fees = extra * max_fee;
|
||||||
let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
|
let total_keypairs = keypairs.len() as u64 + 1; // Add one for funding keypair
|
||||||
let mut total = lamports_per_account * total_keypairs + extra_fees;
|
let mut total = lamports_per_account * total_keypairs + extra_fees;
|
||||||
@ -1134,7 +1134,7 @@ mod tests {
|
|||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_runtime::bank_client::BankClient;
|
use solana_runtime::bank_client::BankClient;
|
||||||
use solana_sdk::client::SyncClient;
|
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;
|
use solana_sdk::genesis_config::create_genesis_config;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1181,8 +1181,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_bench_tps_fund_keys_with_fees() {
|
fn test_bench_tps_fund_keys_with_fees() {
|
||||||
let (mut genesis_config, id) = create_genesis_config(10_000);
|
let (mut genesis_config, id) = create_genesis_config(10_000);
|
||||||
let fee_calculator = FeeCalculator::new(11, 0);
|
let fee_rate_governor = FeeRateGovernor::new(11, 0);
|
||||||
genesis_config.fee_calculator = fee_calculator;
|
genesis_config.fee_rate_governor = fee_rate_governor;
|
||||||
let bank = Bank::new(&genesis_config);
|
let bank = Bank::new(&genesis_config);
|
||||||
let client = Arc::new(BankClient::new(bank));
|
let client = Arc::new(BankClient::new(bank));
|
||||||
let keypair_count = 20;
|
let keypair_count = 20;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clap::{crate_description, crate_name, App, Arg, ArgMatches};
|
use clap::{crate_description, crate_name, App, Arg, ArgMatches};
|
||||||
use solana_faucet::faucet::FAUCET_PORT;
|
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 solana_sdk::signature::{read_keypair_file, Keypair};
|
||||||
use std::{net::SocketAddr, process::exit, time::Duration};
|
use std::{net::SocketAddr, process::exit, time::Duration};
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ impl Default for Config {
|
|||||||
client_ids_and_stake_file: String::new(),
|
client_ids_and_stake_file: String::new(),
|
||||||
write_to_client_file: false,
|
write_to_client_file: false,
|
||||||
read_from_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,
|
multi_client: true,
|
||||||
use_move: false,
|
use_move: false,
|
||||||
num_lamports_per_account: NUM_LAMPORTS_PER_ACCOUNT_DEFAULT,
|
num_lamports_per_account: NUM_LAMPORTS_PER_ACCOUNT_DEFAULT,
|
||||||
|
@ -3,7 +3,7 @@ use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate
|
|||||||
use solana_bench_tps::cli;
|
use solana_bench_tps::cli;
|
||||||
use solana_core::gossip_service::{discover_cluster, get_client, get_multi_client};
|
use solana_core::gossip_service::{discover_cluster, get_client, get_multi_client};
|
||||||
use solana_genesis::Base64Account;
|
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::signature::{Keypair, Signer};
|
||||||
use solana_sdk::system_program;
|
use solana_sdk::system_program;
|
||||||
use std::{collections::HashMap, fs::File, io::prelude::*, path::Path, process::exit, sync::Arc};
|
use std::{collections::HashMap, fs::File, io::prelude::*, path::Path, process::exit, sync::Arc};
|
||||||
@ -41,7 +41,7 @@ fn main() {
|
|||||||
let (keypairs, _) = generate_keypairs(&id, keypair_count as u64);
|
let (keypairs, _) = generate_keypairs(&id, keypair_count as u64);
|
||||||
let num_accounts = keypairs.len() as u64;
|
let num_accounts = keypairs.len() as u64;
|
||||||
let max_fee =
|
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)
|
let num_lamports_per_account = (num_accounts - 1 + NUM_SIGNATURES_FOR_TXS * max_fee)
|
||||||
/ num_accounts
|
/ num_accounts
|
||||||
+ num_lamports_per_account;
|
+ num_lamports_per_account;
|
||||||
|
@ -201,7 +201,7 @@ mod tests {
|
|||||||
fn test_blockhashspec_get_blockhash_fee_calc() {
|
fn test_blockhashspec_get_blockhash_fee_calc() {
|
||||||
let test_blockhash = hash(&[0u8]);
|
let test_blockhash = hash(&[0u8]);
|
||||||
let rpc_blockhash = hash(&[1u8]);
|
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 {
|
let get_recent_blockhash_response = json!(Response {
|
||||||
context: RpcResponseContext { slot: 1 },
|
context: RpcResponseContext { slot: 1 },
|
||||||
value: json!((
|
value: json!((
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use serde_json::{Number, Value};
|
use serde_json::{Number, Value};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
transaction::{self, TransactionError},
|
transaction::{self, TransactionError},
|
||||||
};
|
};
|
||||||
@ -71,6 +71,10 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
|
|||||||
serde_json::to_value(FeeCalculator::default()).unwrap(),
|
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 => {
|
RpcRequest::GetSignatureStatus => {
|
||||||
let response: Option<transaction::Result<()>> = if self.url == "account_in_use" {
|
let response: Option<transaction::Result<()>> = if self.url == "account_in_use" {
|
||||||
Some(Err(TransactionError::AccountInUse))
|
Some(Err(TransactionError::AccountInUse))
|
||||||
|
@ -6,8 +6,8 @@ use crate::{
|
|||||||
rpc_request::RpcRequest,
|
rpc_request::RpcRequest,
|
||||||
rpc_response::{
|
rpc_response::{
|
||||||
Response, RpcAccount, RpcBlockhashFeeCalculator, RpcConfirmedBlock, RpcContactInfo,
|
Response, RpcAccount, RpcBlockhashFeeCalculator, RpcConfirmedBlock, RpcContactInfo,
|
||||||
RpcEpochInfo, RpcKeyedAccount, RpcLeaderSchedule, RpcResponse, RpcVersionInfo,
|
RpcEpochInfo, RpcFeeRateGovernor, RpcKeyedAccount, RpcLeaderSchedule, RpcResponse,
|
||||||
RpcVoteAccountStatus,
|
RpcVersionInfo, RpcVoteAccountStatus,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
@ -18,7 +18,7 @@ use solana_sdk::{
|
|||||||
clock::{Slot, UnixTimestamp, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT},
|
clock::{Slot, UnixTimestamp, DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT},
|
||||||
commitment_config::CommitmentConfig,
|
commitment_config::CommitmentConfig,
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
inflation::Inflation,
|
inflation::Inflation,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
@ -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)> {
|
pub fn get_new_blockhash(&self, blockhash: &Hash) -> io::Result<(Hash, FeeCalculator)> {
|
||||||
let mut num_retries = 0;
|
let mut num_retries = 0;
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
@ -20,6 +20,7 @@ pub enum RpcRequest {
|
|||||||
GetNumBlocksSinceSignatureConfirmation,
|
GetNumBlocksSinceSignatureConfirmation,
|
||||||
GetProgramAccounts,
|
GetProgramAccounts,
|
||||||
GetRecentBlockhash,
|
GetRecentBlockhash,
|
||||||
|
GetFeeRateGovernor,
|
||||||
GetSignatureStatus,
|
GetSignatureStatus,
|
||||||
GetSlot,
|
GetSlot,
|
||||||
GetSlotLeader,
|
GetSlotLeader,
|
||||||
@ -61,6 +62,7 @@ impl RpcRequest {
|
|||||||
}
|
}
|
||||||
RpcRequest::GetProgramAccounts => "getProgramAccounts",
|
RpcRequest::GetProgramAccounts => "getProgramAccounts",
|
||||||
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
|
RpcRequest::GetRecentBlockhash => "getRecentBlockhash",
|
||||||
|
RpcRequest::GetFeeRateGovernor => "getFeeRateGovernor",
|
||||||
RpcRequest::GetSignatureStatus => "getSignatureStatus",
|
RpcRequest::GetSignatureStatus => "getSignatureStatus",
|
||||||
RpcRequest::GetSlot => "getSlot",
|
RpcRequest::GetSlot => "getSlot",
|
||||||
RpcRequest::GetSlotLeader => "getSlotLeader",
|
RpcRequest::GetSlotLeader => "getSlotLeader",
|
||||||
@ -138,6 +140,10 @@ mod tests {
|
|||||||
let request = test_request.build_request_json(1, Value::Null);
|
let request = test_request.build_request_json(1, Value::Null);
|
||||||
assert_eq!(request["method"], "getRecentBlockhash");
|
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 test_request = RpcRequest::GetSlot;
|
||||||
let request = test_request.build_request_json(1, Value::Null);
|
let request = test_request.build_request_json(1, Value::Null);
|
||||||
assert_eq!(request["method"], "getSlot");
|
assert_eq!(request["method"], "getSlot");
|
||||||
|
@ -4,7 +4,7 @@ use jsonrpc_core::Result as JsonResult;
|
|||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
clock::{Epoch, Slot},
|
clock::{Epoch, Slot},
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
message::MessageHeader,
|
message::MessageHeader,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
transaction::{Result, Transaction},
|
transaction::{Result, Transaction},
|
||||||
@ -152,6 +152,12 @@ pub struct RpcBlockhashFeeCalculator {
|
|||||||
pub fee_calculator: FeeCalculator,
|
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)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RpcKeyedAccount {
|
pub struct RpcKeyedAccount {
|
||||||
|
@ -11,7 +11,7 @@ use solana_sdk::{
|
|||||||
client::{AsyncClient, Client, SyncClient},
|
client::{AsyncClient, Client, SyncClient},
|
||||||
clock::MAX_PROCESSING_AGE,
|
clock::MAX_PROCESSING_AGE,
|
||||||
commitment_config::CommitmentConfig,
|
commitment_config::CommitmentConfig,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::Instruction,
|
instruction::Instruction,
|
||||||
message::Message,
|
message::Message,
|
||||||
@ -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(
|
fn get_signature_status(
|
||||||
&self,
|
&self,
|
||||||
signature: &Signature,
|
signature: &Signature,
|
||||||
|
@ -9,9 +9,9 @@ use jsonrpc_core::{Error, Metadata, Result};
|
|||||||
use jsonrpc_derive::rpc;
|
use jsonrpc_derive::rpc;
|
||||||
use solana_client::rpc_response::{
|
use solana_client::rpc_response::{
|
||||||
Response, RpcAccount, RpcBlockCommitment, RpcBlockhashFeeCalculator, RpcConfirmedBlock,
|
Response, RpcAccount, RpcBlockCommitment, RpcBlockhashFeeCalculator, RpcConfirmedBlock,
|
||||||
RpcContactInfo, RpcEpochInfo, RpcKeyedAccount, RpcLeaderSchedule, RpcResponseContext,
|
RpcContactInfo, RpcEpochInfo, RpcFeeRateGovernor, RpcKeyedAccount, RpcLeaderSchedule,
|
||||||
RpcSignatureConfirmation, RpcStorageTurn, RpcTransactionEncoding, RpcVersionInfo,
|
RpcResponseContext, RpcSignatureConfirmation, RpcStorageTurn, RpcTransactionEncoding,
|
||||||
RpcVoteAccountInfo, RpcVoteAccountStatus,
|
RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus,
|
||||||
};
|
};
|
||||||
use solana_faucet::faucet::request_airdrop_transaction;
|
use solana_faucet::faucet::request_airdrop_transaction;
|
||||||
use solana_ledger::{
|
use solana_ledger::{
|
||||||
@ -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(
|
pub fn confirm_transaction(
|
||||||
&self,
|
&self,
|
||||||
signature: Result<Signature>,
|
signature: Result<Signature>,
|
||||||
@ -491,6 +502,9 @@ pub trait RpcSol {
|
|||||||
commitment: Option<CommitmentConfig>,
|
commitment: Option<CommitmentConfig>,
|
||||||
) -> RpcResponse<RpcBlockhashFeeCalculator>;
|
) -> RpcResponse<RpcBlockhashFeeCalculator>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getFeeRateGovernor")]
|
||||||
|
fn get_fee_rate_governor(&self, meta: Self::Metadata) -> RpcResponse<RpcFeeRateGovernor>;
|
||||||
|
|
||||||
#[rpc(meta, name = "getSignatureStatus")]
|
#[rpc(meta, name = "getSignatureStatus")]
|
||||||
fn get_signature_status(
|
fn get_signature_status(
|
||||||
&self,
|
&self,
|
||||||
@ -813,6 +827,14 @@ impl RpcSol for RpcSolImpl {
|
|||||||
.get_recent_blockhash(commitment)
|
.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(
|
fn get_signature_status(
|
||||||
&self,
|
&self,
|
||||||
meta: Self::Metadata,
|
meta: Self::Metadata,
|
||||||
@ -1770,8 +1792,32 @@ pub mod tests {
|
|||||||
"value":{
|
"value":{
|
||||||
"blockhash": blockhash.to_string(),
|
"blockhash": blockhash.to_string(),
|
||||||
"feeCalculator": {
|
"feeCalculator": {
|
||||||
"burnPercent": DEFAULT_BURN_PERCENT,
|
|
||||||
"lamportsPerSignature": 0,
|
"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,
|
"maxLamportsPerSignature": 0,
|
||||||
"minLamportsPerSignature": 0,
|
"minLamportsPerSignature": 0,
|
||||||
"targetLamportsPerSignature": 0,
|
"targetLamportsPerSignature": 0,
|
||||||
|
@ -680,7 +680,7 @@ impl TestValidator {
|
|||||||
|
|
||||||
pub fn run_with_options(options: TestValidatorOptions) -> Self {
|
pub fn run_with_options(options: TestValidatorOptions) -> Self {
|
||||||
use crate::genesis_utils::{create_genesis_config_with_leader_ex, GenesisConfigInfo};
|
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 {
|
let TestValidatorOptions {
|
||||||
fees,
|
fees,
|
||||||
@ -706,7 +706,7 @@ impl TestValidator {
|
|||||||
|
|
||||||
genesis_config.rent.lamports_per_byte_year = 1;
|
genesis_config.rent.lamports_per_byte_year = 1;
|
||||||
genesis_config.rent.exemption_threshold = 1.0;
|
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);
|
let (ledger_path, blockhash) = create_new_tmp_ledger!(&genesis_config);
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ To interact with a Solana node inside a JavaScript application, use the [solana-
|
|||||||
* [getConfirmedBlocks](jsonrpc-api.md#getconfirmedblocks)
|
* [getConfirmedBlocks](jsonrpc-api.md#getconfirmedblocks)
|
||||||
* [getEpochInfo](jsonrpc-api.md#getepochinfo)
|
* [getEpochInfo](jsonrpc-api.md#getepochinfo)
|
||||||
* [getEpochSchedule](jsonrpc-api.md#getepochschedule)
|
* [getEpochSchedule](jsonrpc-api.md#getepochschedule)
|
||||||
|
* [getFeeRateGovernor](jsonrpc-api.md#getfeerategovernor)
|
||||||
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
|
* [getGenesisHash](jsonrpc-api.md#getgenesishash)
|
||||||
* [getInflation](jsonrpc-api.md#getinflation)
|
* [getInflation](jsonrpc-api.md#getinflation)
|
||||||
* [getLeaderSchedule](jsonrpc-api.md#getleaderschedule)
|
* [getLeaderSchedule](jsonrpc-api.md#getleaderschedule)
|
||||||
@ -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}
|
{"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
|
### getGenesisHash
|
||||||
|
|
||||||
Returns the genesis hash
|
Returns the genesis hash
|
||||||
|
@ -11,7 +11,7 @@ use solana_sdk::{
|
|||||||
account::Account,
|
account::Account,
|
||||||
clock,
|
clock,
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeRateGovernor,
|
||||||
genesis_config::{GenesisConfig, OperatingMode},
|
genesis_config::{GenesisConfig, OperatingMode},
|
||||||
native_token::sol_to_lamports,
|
native_token::sol_to_lamports,
|
||||||
poh_config::PohConfig,
|
poh_config::PohConfig,
|
||||||
@ -99,16 +99,16 @@ pub fn load_genesis_accounts(file: &str, genesis_config: &mut GenesisConfig) ->
|
|||||||
|
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
let fee_calculator = FeeCalculator::default();
|
let fee_rate_governor = FeeRateGovernor::default();
|
||||||
let (
|
let (
|
||||||
default_target_lamports_per_signature,
|
default_target_lamports_per_signature,
|
||||||
default_target_signatures_per_slot,
|
default_target_signatures_per_slot,
|
||||||
default_fee_burn_percentage,
|
default_fee_burn_percentage,
|
||||||
) = {
|
) = {
|
||||||
(
|
(
|
||||||
&fee_calculator.target_lamports_per_signature.to_string(),
|
&fee_rate_governor.target_lamports_per_signature.to_string(),
|
||||||
&fee_calculator.target_signatures_per_slot.to_string(),
|
&fee_rate_governor.target_signatures_per_slot.to_string(),
|
||||||
&fee_calculator.burn_percent.to_string(),
|
&fee_rate_governor.burn_percent.to_string(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -449,11 +449,11 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
|
|
||||||
let ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64);
|
let ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64);
|
||||||
|
|
||||||
let mut fee_calculator = FeeCalculator::new(
|
let mut fee_rate_governor = FeeRateGovernor::new(
|
||||||
value_t_or_exit!(matches, "target_lamports_per_signature", u64),
|
value_t_or_exit!(matches, "target_lamports_per_signature", u64),
|
||||||
value_t_or_exit!(matches, "target_signatures_per_slot", usize),
|
value_t_or_exit!(matches, "target_signatures_per_slot", u64),
|
||||||
);
|
);
|
||||||
fee_calculator.burn_percent = value_t_or_exit!(matches, "fee_burn_percentage", u8);
|
fee_rate_governor.burn_percent = value_t_or_exit!(matches, "fee_burn_percentage", u8);
|
||||||
|
|
||||||
let mut poh_config = PohConfig::default();
|
let mut poh_config = PohConfig::default();
|
||||||
poh_config.target_tick_duration = if matches.is_present("target_tick_duration") {
|
poh_config.target_tick_duration = if matches.is_present("target_tick_duration") {
|
||||||
@ -513,7 +513,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
ticks_per_slot,
|
ticks_per_slot,
|
||||||
epoch_schedule,
|
epoch_schedule,
|
||||||
inflation,
|
inflation,
|
||||||
fee_calculator,
|
fee_rate_governor,
|
||||||
rent,
|
rent,
|
||||||
poh_config,
|
poh_config,
|
||||||
operating_mode,
|
operating_mode,
|
||||||
|
@ -25,7 +25,7 @@ pub struct StakerInfo {
|
|||||||
// lamports to cover TX fees (delegation) for one year,
|
// lamports to cover TX fees (delegation) for one year,
|
||||||
// and we support one delegation per epoch
|
// and we support one delegation per epoch
|
||||||
fn calculate_staker_fees(genesis_config: &GenesisConfig, years: f64) -> u64 {
|
fn calculate_staker_fees(genesis_config: &GenesisConfig, years: f64) -> u64 {
|
||||||
genesis_config.fee_calculator.max_lamports_per_signature
|
genesis_config.fee_rate_governor.max_lamports_per_signature
|
||||||
* genesis_config.epoch_schedule.get_epoch(years_as_slots(
|
* genesis_config.epoch_schedule.get_epoch(years_as_slots(
|
||||||
years,
|
years,
|
||||||
&genesis_config.poh_config.target_tick_duration,
|
&genesis_config.poh_config.target_tick_duration,
|
||||||
|
@ -36,8 +36,8 @@ fn process_instruction(
|
|||||||
info!("Fees identifier:");
|
info!("Fees identifier:");
|
||||||
sysvar::fees::id().log();
|
sysvar::fees::id().log();
|
||||||
let fees = Fees::from_account_info(&accounts[3]).expect("fees");
|
let fees = Fees::from_account_info(&accounts[3]).expect("fees");
|
||||||
let burn = fees.fee_calculator.burn(42);
|
let fee_calculator = fees.fee_calculator;
|
||||||
assert_eq!(burn, (21, 21));
|
assert_eq!(fee_calculator.lamports_per_signature, 0);
|
||||||
|
|
||||||
// Rewards
|
// Rewards
|
||||||
info!("Rewards identifier:");
|
info!("Rewards identifier:");
|
||||||
|
@ -853,7 +853,7 @@ mod tests {
|
|||||||
instructions,
|
instructions,
|
||||||
);
|
);
|
||||||
|
|
||||||
let fee_calculator = FeeCalculator::new(10, 0);
|
let fee_calculator = FeeCalculator::new(10);
|
||||||
assert_eq!(fee_calculator.calculate_fee(tx.message()), 10);
|
assert_eq!(fee_calculator.calculate_fee(tx.message()), 10);
|
||||||
|
|
||||||
let loaded_accounts =
|
let loaded_accounts =
|
||||||
@ -918,7 +918,7 @@ mod tests {
|
|||||||
let min_balance = rent_collector
|
let min_balance = rent_collector
|
||||||
.rent
|
.rent
|
||||||
.minimum_balance(nonce_state::NonceState::size());
|
.minimum_balance(nonce_state::NonceState::size());
|
||||||
let fee_calculator = FeeCalculator::new(min_balance, 0);
|
let fee_calculator = FeeCalculator::new(min_balance);
|
||||||
let nonce = Keypair::new();
|
let nonce = Keypair::new();
|
||||||
let mut accounts = vec![(
|
let mut accounts = vec![(
|
||||||
nonce.pubkey(),
|
nonce.pubkey(),
|
||||||
|
@ -35,7 +35,7 @@ use solana_sdk::{
|
|||||||
account::Account,
|
account::Account,
|
||||||
clock::{get_segment_from_slot, Epoch, Slot, UnixTimestamp, MAX_RECENT_BLOCKHASHES},
|
clock::{get_segment_from_slot, Epoch, Slot, UnixTimestamp, MAX_RECENT_BLOCKHASHES},
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
genesis_config::GenesisConfig,
|
genesis_config::GenesisConfig,
|
||||||
hard_forks::HardForks,
|
hard_forks::HardForks,
|
||||||
hash::{extend_and_hash, hashv, Hash},
|
hash::{extend_and_hash, hashv, Hash},
|
||||||
@ -302,6 +302,9 @@ pub struct Bank {
|
|||||||
/// Latest transaction fees for transactions processed by this bank
|
/// Latest transaction fees for transactions processed by this bank
|
||||||
fee_calculator: FeeCalculator,
|
fee_calculator: FeeCalculator,
|
||||||
|
|
||||||
|
/// Track cluster signature throughput and adjust fee rate
|
||||||
|
fee_rate_governor: FeeRateGovernor,
|
||||||
|
|
||||||
/// Rent that have been collected
|
/// Rent that have been collected
|
||||||
#[serde(serialize_with = "serialize_atomicu64")]
|
#[serde(serialize_with = "serialize_atomicu64")]
|
||||||
#[serde(deserialize_with = "deserialize_atomicu64")]
|
#[serde(deserialize_with = "deserialize_atomicu64")]
|
||||||
@ -401,6 +404,9 @@ impl Bank {
|
|||||||
let epoch_schedule = parent.epoch_schedule;
|
let epoch_schedule = parent.epoch_schedule;
|
||||||
let epoch = epoch_schedule.get_epoch(slot);
|
let epoch = epoch_schedule.get_epoch(slot);
|
||||||
|
|
||||||
|
let fee_rate_governor =
|
||||||
|
FeeRateGovernor::new_derived(&parent.fee_rate_governor, parent.signature_count());
|
||||||
|
|
||||||
let mut new = Bank {
|
let mut new = Bank {
|
||||||
rc,
|
rc,
|
||||||
src,
|
src,
|
||||||
@ -420,10 +426,8 @@ impl Bank {
|
|||||||
rent_collector: parent.rent_collector.clone_with_epoch(epoch),
|
rent_collector: parent.rent_collector.clone_with_epoch(epoch),
|
||||||
max_tick_height: (slot + 1) * parent.ticks_per_slot,
|
max_tick_height: (slot + 1) * parent.ticks_per_slot,
|
||||||
block_height: parent.block_height + 1,
|
block_height: parent.block_height + 1,
|
||||||
fee_calculator: FeeCalculator::new_derived(
|
fee_calculator: fee_rate_governor.create_fee_calculator(),
|
||||||
&parent.fee_calculator,
|
fee_rate_governor,
|
||||||
parent.signature_count() as usize,
|
|
||||||
),
|
|
||||||
capitalization: AtomicU64::new(parent.capitalization()),
|
capitalization: AtomicU64::new(parent.capitalization()),
|
||||||
inflation: parent.inflation.clone(),
|
inflation: parent.inflation.clone(),
|
||||||
transaction_count: AtomicU64::new(parent.transaction_count()),
|
transaction_count: AtomicU64::new(parent.transaction_count()),
|
||||||
@ -745,7 +749,7 @@ impl Bank {
|
|||||||
let collector_fees = self.collector_fees.load(Ordering::Relaxed) as u64;
|
let collector_fees = self.collector_fees.load(Ordering::Relaxed) as u64;
|
||||||
|
|
||||||
if collector_fees != 0 {
|
if collector_fees != 0 {
|
||||||
let (unburned, burned) = self.fee_calculator.burn(collector_fees);
|
let (unburned, burned) = self.fee_rate_governor.burn(collector_fees);
|
||||||
// burn a portion of fees
|
// burn a portion of fees
|
||||||
self.deposit(&self.collector_id, unburned);
|
self.deposit(&self.collector_id, unburned);
|
||||||
self.capitalization.fetch_sub(burned, Ordering::Relaxed);
|
self.capitalization.fetch_sub(burned, Ordering::Relaxed);
|
||||||
@ -811,7 +815,8 @@ impl Bank {
|
|||||||
|
|
||||||
fn process_genesis_config(&mut self, genesis_config: &GenesisConfig) {
|
fn process_genesis_config(&mut self, genesis_config: &GenesisConfig) {
|
||||||
// Bootstrap validator collects fees until `new_from_parent` is called.
|
// Bootstrap validator collects fees until `new_from_parent` is called.
|
||||||
self.fee_calculator = genesis_config.fee_calculator.clone();
|
self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
|
||||||
|
self.fee_calculator = self.fee_rate_governor.create_fee_calculator();
|
||||||
self.update_fees();
|
self.update_fees();
|
||||||
|
|
||||||
for (pubkey, account) in genesis_config.accounts.iter() {
|
for (pubkey, account) in genesis_config.accounts.iter() {
|
||||||
@ -905,6 +910,10 @@ impl Bank {
|
|||||||
blockhash_queue.get_fee_calculator(hash).cloned()
|
blockhash_queue.get_fee_calculator(hash).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_fee_rate_governor(&self) -> &FeeRateGovernor {
|
||||||
|
&self.fee_rate_governor
|
||||||
|
}
|
||||||
|
|
||||||
pub fn confirmed_last_blockhash(&self) -> (Hash, FeeCalculator) {
|
pub fn confirmed_last_blockhash(&self) -> (Hash, FeeCalculator) {
|
||||||
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
|
const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
|
||||||
|
|
||||||
@ -3290,7 +3299,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_detect_failed_duplicate_transactions() {
|
fn test_detect_failed_duplicate_transactions() {
|
||||||
let (mut genesis_config, mint_keypair) = create_genesis_config(2);
|
let (mut genesis_config, mint_keypair) = create_genesis_config(2);
|
||||||
genesis_config.fee_calculator.lamports_per_signature = 1;
|
genesis_config.fee_rate_governor = FeeRateGovernor::new(1, 0);
|
||||||
let bank = Bank::new(&genesis_config);
|
let bank = Bank::new(&genesis_config);
|
||||||
|
|
||||||
let dest = Keypair::new();
|
let dest = Keypair::new();
|
||||||
@ -3450,11 +3459,14 @@ mod tests {
|
|||||||
mint_keypair,
|
mint_keypair,
|
||||||
..
|
..
|
||||||
} = create_genesis_config_with_leader(mint, &leader, 3);
|
} = create_genesis_config_with_leader(mint, &leader, 3);
|
||||||
genesis_config.fee_calculator.lamports_per_signature = 4; // something divisible by 2
|
genesis_config.fee_rate_governor = FeeRateGovernor::new(4, 0); // something divisible by 2
|
||||||
|
|
||||||
let expected_fee_paid = genesis_config.fee_calculator.lamports_per_signature;
|
let expected_fee_paid = genesis_config
|
||||||
|
.fee_rate_governor
|
||||||
|
.create_fee_calculator()
|
||||||
|
.lamports_per_signature;
|
||||||
let (expected_fee_collected, expected_fee_burned) =
|
let (expected_fee_collected, expected_fee_burned) =
|
||||||
genesis_config.fee_calculator.burn(expected_fee_paid);
|
genesis_config.fee_rate_governor.burn(expected_fee_paid);
|
||||||
|
|
||||||
let mut bank = Bank::new(&genesis_config);
|
let mut bank = Bank::new(&genesis_config);
|
||||||
|
|
||||||
@ -3521,8 +3533,10 @@ mod tests {
|
|||||||
mint_keypair,
|
mint_keypair,
|
||||||
..
|
..
|
||||||
} = create_genesis_config_with_leader(1_000_000, &leader, 3);
|
} = create_genesis_config_with_leader(1_000_000, &leader, 3);
|
||||||
genesis_config.fee_calculator.target_lamports_per_signature = 1000;
|
genesis_config
|
||||||
genesis_config.fee_calculator.target_signatures_per_slot = 1;
|
.fee_rate_governor
|
||||||
|
.target_lamports_per_signature = 1000;
|
||||||
|
genesis_config.fee_rate_governor.target_signatures_per_slot = 1;
|
||||||
|
|
||||||
let mut bank = Bank::new(&genesis_config);
|
let mut bank = Bank::new(&genesis_config);
|
||||||
goto_end_of_slot(&mut bank);
|
goto_end_of_slot(&mut bank);
|
||||||
@ -3571,7 +3585,7 @@ mod tests {
|
|||||||
mint_keypair,
|
mint_keypair,
|
||||||
..
|
..
|
||||||
} = create_genesis_config_with_leader(100, &leader, 3);
|
} = create_genesis_config_with_leader(100, &leader, 3);
|
||||||
genesis_config.fee_calculator.lamports_per_signature = 2;
|
genesis_config.fee_rate_governor = FeeRateGovernor::new(2, 0);
|
||||||
let bank = Bank::new(&genesis_config);
|
let bank = Bank::new(&genesis_config);
|
||||||
|
|
||||||
let key = Keypair::new();
|
let key = Keypair::new();
|
||||||
@ -3598,7 +3612,7 @@ mod tests {
|
|||||||
bank.get_balance(&leader),
|
bank.get_balance(&leader),
|
||||||
initial_balance
|
initial_balance
|
||||||
+ bank
|
+ bank
|
||||||
.fee_calculator
|
.fee_rate_governor
|
||||||
.burn(bank.fee_calculator.lamports_per_signature * 2)
|
.burn(bank.fee_calculator.lamports_per_signature * 2)
|
||||||
.0
|
.0
|
||||||
);
|
);
|
||||||
@ -4548,15 +4562,20 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bank_inherit_fee_calculator() {
|
fn test_bank_inherit_fee_rate_governor() {
|
||||||
let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
|
let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
|
||||||
genesis_config.fee_calculator.target_lamports_per_signature = 123;
|
genesis_config
|
||||||
|
.fee_rate_governor
|
||||||
|
.target_lamports_per_signature = 123;
|
||||||
|
|
||||||
let bank0 = Arc::new(Bank::new(&genesis_config));
|
let bank0 = Arc::new(Bank::new(&genesis_config));
|
||||||
let bank1 = Arc::new(new_from_parent(&bank0));
|
let bank1 = Arc::new(new_from_parent(&bank0));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bank0.fee_calculator.target_lamports_per_signature / 2,
|
bank0.fee_rate_governor.target_lamports_per_signature / 2,
|
||||||
bank1.fee_calculator.lamports_per_signature
|
bank1
|
||||||
|
.fee_rate_governor
|
||||||
|
.create_fee_calculator()
|
||||||
|
.lamports_per_signature
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4659,7 +4678,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_bank_fees_account() {
|
fn test_bank_fees_account() {
|
||||||
let (mut genesis_config, _) = create_genesis_config(500);
|
let (mut genesis_config, _) = create_genesis_config(500);
|
||||||
genesis_config.fee_calculator.lamports_per_signature = 12345;
|
genesis_config.fee_rate_governor = FeeRateGovernor::new(12345, 0);
|
||||||
let bank = Arc::new(Bank::new(&genesis_config));
|
let bank = Arc::new(Bank::new(&genesis_config));
|
||||||
|
|
||||||
let fees_account = bank.get_account(&sysvar::fees::id()).unwrap();
|
let fees_account = bank.get_account(&sysvar::fees::id()).unwrap();
|
||||||
@ -5443,8 +5462,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_pre_post_transaction_balances() {
|
fn test_pre_post_transaction_balances() {
|
||||||
let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
|
let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
|
||||||
let fee_calculator = FeeCalculator::new(1, 0);
|
let fee_rate_governor = FeeRateGovernor::new(1, 0);
|
||||||
genesis_config.fee_calculator = fee_calculator;
|
genesis_config.fee_rate_governor = fee_rate_governor;
|
||||||
let parent = Arc::new(Bank::new(&genesis_config));
|
let parent = Arc::new(Bank::new(&genesis_config));
|
||||||
let bank0 = Arc::new(new_from_parent(&parent));
|
let bank0 = Arc::new(new_from_parent(&parent));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use solana_sdk::{
|
|||||||
account::Account,
|
account::Account,
|
||||||
client::{AsyncClient, Client, SyncClient},
|
client::{AsyncClient, Client, SyncClient},
|
||||||
commitment_config::CommitmentConfig,
|
commitment_config::CommitmentConfig,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::Instruction,
|
instruction::Instruction,
|
||||||
message::Message,
|
message::Message,
|
||||||
@ -137,6 +137,10 @@ impl SyncClient for BankClient {
|
|||||||
Ok(self.bank.last_blockhash_with_fee_calculator())
|
Ok(self.bank.last_blockhash_with_fee_calculator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor> {
|
||||||
|
Ok(self.bank.get_fee_rate_governor().clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_signature_status(
|
fn get_signature_status(
|
||||||
&self,
|
&self,
|
||||||
signature: &Signature,
|
signature: &Signature,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeRateGovernor,
|
||||||
genesis_config::GenesisConfig,
|
genesis_config::GenesisConfig,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
@ -140,11 +140,11 @@ pub fn create_genesis_config_with_leader_ex(
|
|||||||
solana_stake_program!(),
|
solana_stake_program!(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let fee_calculator = FeeCalculator::new(0, 0); // most tests can't handle transaction fees
|
let fee_rate_governor = FeeRateGovernor::new(0, 0); // most tests can't handle transaction fees
|
||||||
let mut genesis_config = GenesisConfig {
|
let mut genesis_config = GenesisConfig {
|
||||||
accounts,
|
accounts,
|
||||||
native_instruction_processors,
|
native_instruction_processors,
|
||||||
fee_calculator,
|
fee_rate_governor,
|
||||||
rent,
|
rent,
|
||||||
..GenesisConfig::default()
|
..GenesisConfig::default()
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ use crate::{
|
|||||||
account::Account,
|
account::Account,
|
||||||
clock::Slot,
|
clock::Slot,
|
||||||
commitment_config::CommitmentConfig,
|
commitment_config::CommitmentConfig,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::Instruction,
|
instruction::Instruction,
|
||||||
message::Message,
|
message::Message,
|
||||||
@ -72,6 +72,9 @@ pub trait SyncClient {
|
|||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
) -> Result<(Hash, FeeCalculator)>;
|
) -> Result<(Hash, FeeCalculator)>;
|
||||||
|
|
||||||
|
/// Get recent fee rate governor
|
||||||
|
fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor>;
|
||||||
|
|
||||||
/// Get signature status.
|
/// Get signature status.
|
||||||
fn get_signature_status(
|
fn get_signature_status(
|
||||||
&self,
|
&self,
|
||||||
|
@ -8,6 +8,35 @@ pub struct FeeCalculator {
|
|||||||
// The current cost of a signature This amount may increase/decrease over time based on
|
// The current cost of a signature This amount may increase/decrease over time based on
|
||||||
// cluster processing load.
|
// cluster processing load.
|
||||||
pub lamports_per_signature: u64,
|
pub lamports_per_signature: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FeeCalculator {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
lamports_per_signature: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FeeCalculator {
|
||||||
|
pub fn new(lamports_per_signature: u64) -> Self {
|
||||||
|
Self {
|
||||||
|
lamports_per_signature,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn calculate_fee(&self, message: &Message) -> u64 {
|
||||||
|
self.lamports_per_signature * u64::from(message.header.num_required_signatures)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct FeeRateGovernor {
|
||||||
|
// The current cost of a signature This amount may increase/decrease over time based on
|
||||||
|
// cluster processing load.
|
||||||
|
#[serde(skip)]
|
||||||
|
lamports_per_signature: u64,
|
||||||
|
|
||||||
// The target cost of a signature when the cluster is operating around target_signatures_per_slot
|
// The target cost of a signature when the cluster is operating around target_signatures_per_slot
|
||||||
// signatures
|
// signatures
|
||||||
@ -16,7 +45,7 @@ pub struct FeeCalculator {
|
|||||||
// Used to estimate the desired processing capacity of the cluster. As the signatures for
|
// Used to estimate the desired processing capacity of the cluster. As the signatures for
|
||||||
// recent slots are fewer/greater than this value, lamports_per_signature will decrease/increase
|
// recent slots are fewer/greater than this value, lamports_per_signature will decrease/increase
|
||||||
// for the next slot. A value of 0 disables lamports_per_signature fee adjustments
|
// for the next slot. A value of 0 disables lamports_per_signature fee adjustments
|
||||||
pub target_signatures_per_slot: usize,
|
pub target_signatures_per_slot: u64,
|
||||||
|
|
||||||
pub min_lamports_per_signature: u64,
|
pub min_lamports_per_signature: u64,
|
||||||
pub max_lamports_per_signature: u64,
|
pub max_lamports_per_signature: u64,
|
||||||
@ -26,15 +55,15 @@ pub struct FeeCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const DEFAULT_TARGET_LAMPORTS_PER_SIGNATURE: u64 = 10_000;
|
pub const DEFAULT_TARGET_LAMPORTS_PER_SIGNATURE: u64 = 10_000;
|
||||||
pub const DEFAULT_TARGET_SIGNATURES_PER_SLOT: usize =
|
pub const DEFAULT_TARGET_SIGNATURES_PER_SLOT: u64 =
|
||||||
50_000 * DEFAULT_TICKS_PER_SLOT as usize / DEFAULT_TICKS_PER_SECOND as usize;
|
50_000 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND;
|
||||||
|
|
||||||
// Percentage of tx fees to burn
|
// Percentage of tx fees to burn
|
||||||
pub const DEFAULT_BURN_PERCENT: u8 = 50;
|
pub const DEFAULT_BURN_PERCENT: u8 = 50;
|
||||||
|
|
||||||
impl Default for FeeCalculator {
|
impl Default for FeeRateGovernor {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
FeeCalculator {
|
Self {
|
||||||
lamports_per_signature: 0,
|
lamports_per_signature: 0,
|
||||||
target_lamports_per_signature: DEFAULT_TARGET_LAMPORTS_PER_SIGNATURE,
|
target_lamports_per_signature: DEFAULT_TARGET_LAMPORTS_PER_SIGNATURE,
|
||||||
target_signatures_per_slot: DEFAULT_TARGET_SIGNATURES_PER_SLOT,
|
target_signatures_per_slot: DEFAULT_TARGET_SIGNATURES_PER_SLOT,
|
||||||
@ -45,23 +74,23 @@ impl Default for FeeCalculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FeeCalculator {
|
impl FeeRateGovernor {
|
||||||
pub fn new(target_lamports_per_signature: u64, target_signatures_per_slot: usize) -> Self {
|
pub fn new(target_lamports_per_signature: u64, target_signatures_per_slot: u64) -> Self {
|
||||||
let base_fee_calculator = Self {
|
let base_fee_rate_governor = Self {
|
||||||
target_lamports_per_signature,
|
target_lamports_per_signature,
|
||||||
lamports_per_signature: target_lamports_per_signature,
|
lamports_per_signature: target_lamports_per_signature,
|
||||||
target_signatures_per_slot,
|
target_signatures_per_slot,
|
||||||
..FeeCalculator::default()
|
..FeeRateGovernor::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::new_derived(&base_fee_calculator, 0)
|
Self::new_derived(&base_fee_rate_governor, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_derived(
|
pub fn new_derived(
|
||||||
base_fee_calculator: &FeeCalculator,
|
base_fee_rate_governor: &FeeRateGovernor,
|
||||||
latest_signatures_per_slot: usize,
|
latest_signatures_per_slot: u64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut me = base_fee_calculator.clone();
|
let mut me = base_fee_rate_governor.clone();
|
||||||
|
|
||||||
if me.target_signatures_per_slot > 0 {
|
if me.target_signatures_per_slot > 0 {
|
||||||
// lamports_per_signature can range from 50% to 1000% of
|
// lamports_per_signature can range from 50% to 1000% of
|
||||||
@ -74,7 +103,7 @@ impl FeeCalculator {
|
|||||||
me.max_lamports_per_signature
|
me.max_lamports_per_signature
|
||||||
.min(me.min_lamports_per_signature.max(
|
.min(me.min_lamports_per_signature.max(
|
||||||
me.target_lamports_per_signature
|
me.target_lamports_per_signature
|
||||||
* std::cmp::min(latest_signatures_per_slot, std::u32::MAX as usize)
|
* std::cmp::min(latest_signatures_per_slot, std::u32::MAX as u64)
|
||||||
as u64
|
as u64
|
||||||
/ me.target_signatures_per_slot as u64,
|
/ me.target_signatures_per_slot as u64,
|
||||||
));
|
));
|
||||||
@ -85,7 +114,7 @@ impl FeeCalculator {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let gap = desired_lamports_per_signature as i64
|
let gap = desired_lamports_per_signature as i64
|
||||||
- base_fee_calculator.lamports_per_signature as i64;
|
- base_fee_rate_governor.lamports_per_signature as i64;
|
||||||
|
|
||||||
if gap == 0 {
|
if gap == 0 {
|
||||||
me.lamports_per_signature = desired_lamports_per_signature;
|
me.lamports_per_signature = desired_lamports_per_signature;
|
||||||
@ -104,11 +133,12 @@ impl FeeCalculator {
|
|||||||
me.lamports_per_signature =
|
me.lamports_per_signature =
|
||||||
me.max_lamports_per_signature
|
me.max_lamports_per_signature
|
||||||
.min(me.min_lamports_per_signature.max(
|
.min(me.min_lamports_per_signature.max(
|
||||||
(base_fee_calculator.lamports_per_signature as i64 + gap_adjust) as u64,
|
(base_fee_rate_governor.lamports_per_signature as i64 + gap_adjust)
|
||||||
|
as u64,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
me.lamports_per_signature = base_fee_calculator.target_lamports_per_signature;
|
me.lamports_per_signature = base_fee_rate_governor.target_lamports_per_signature;
|
||||||
me.min_lamports_per_signature = me.target_lamports_per_signature;
|
me.min_lamports_per_signature = me.target_lamports_per_signature;
|
||||||
me.max_lamports_per_signature = me.target_lamports_per_signature;
|
me.max_lamports_per_signature = me.target_lamports_per_signature;
|
||||||
}
|
}
|
||||||
@ -119,15 +149,18 @@ impl FeeCalculator {
|
|||||||
me
|
me
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_fee(&self, message: &Message) -> u64 {
|
|
||||||
self.lamports_per_signature * u64::from(message.header.num_required_signatures)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// calculate unburned fee from a fee total, returns (unburned, burned)
|
/// calculate unburned fee from a fee total, returns (unburned, burned)
|
||||||
pub fn burn(&self, fees: u64) -> (u64, u64) {
|
pub fn burn(&self, fees: u64) -> (u64, u64) {
|
||||||
let burned = fees * u64::from(self.burn_percent) / 100;
|
let burned = fees * u64::from(self.burn_percent) / 100;
|
||||||
(fees - burned, burned)
|
(fees - burned, burned)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// create a FeeCalculator based on current cluster signature throughput
|
||||||
|
pub fn create_fee_calculator(&self) -> FeeCalculator {
|
||||||
|
FeeCalculator {
|
||||||
|
lamports_per_signature: self.lamports_per_signature,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -136,15 +169,15 @@ mod tests {
|
|||||||
use crate::{pubkey::Pubkey, system_instruction};
|
use crate::{pubkey::Pubkey, system_instruction};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fee_calculator_burn() {
|
fn test_fee_rate_governor_burn() {
|
||||||
let mut fee_calculator = FeeCalculator::default();
|
let mut fee_rate_governor = FeeRateGovernor::default();
|
||||||
assert_eq!(fee_calculator.burn(2), (1, 1));
|
assert_eq!(fee_rate_governor.burn(2), (1, 1));
|
||||||
|
|
||||||
fee_calculator.burn_percent = 0;
|
fee_rate_governor.burn_percent = 0;
|
||||||
assert_eq!(fee_calculator.burn(2), (2, 0));
|
assert_eq!(fee_rate_governor.burn(2), (2, 0));
|
||||||
|
|
||||||
fee_calculator.burn_percent = 100;
|
fee_rate_governor.burn_percent = 100;
|
||||||
assert_eq!(fee_calculator.burn(2), (0, 2));
|
assert_eq!(fee_rate_governor.burn(2), (0, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -154,27 +187,27 @@ mod tests {
|
|||||||
assert_eq!(FeeCalculator::default().calculate_fee(&message), 0);
|
assert_eq!(FeeCalculator::default().calculate_fee(&message), 0);
|
||||||
|
|
||||||
// No signature, no fee.
|
// No signature, no fee.
|
||||||
assert_eq!(FeeCalculator::new(1, 0).calculate_fee(&message), 0);
|
assert_eq!(FeeCalculator::new(1).calculate_fee(&message), 0);
|
||||||
|
|
||||||
// One signature, a fee.
|
// One signature, a fee.
|
||||||
let pubkey0 = Pubkey::new(&[0; 32]);
|
let pubkey0 = Pubkey::new(&[0; 32]);
|
||||||
let pubkey1 = Pubkey::new(&[1; 32]);
|
let pubkey1 = Pubkey::new(&[1; 32]);
|
||||||
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
|
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
|
||||||
let message = Message::new(vec![ix0]);
|
let message = Message::new(vec![ix0]);
|
||||||
assert_eq!(FeeCalculator::new(2, 0).calculate_fee(&message), 2);
|
assert_eq!(FeeCalculator::new(2).calculate_fee(&message), 2);
|
||||||
|
|
||||||
// Two signatures, double the fee.
|
// Two signatures, double the fee.
|
||||||
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
|
let ix0 = system_instruction::transfer(&pubkey0, &pubkey1, 1);
|
||||||
let ix1 = system_instruction::transfer(&pubkey1, &pubkey0, 1);
|
let ix1 = system_instruction::transfer(&pubkey1, &pubkey0, 1);
|
||||||
let message = Message::new(vec![ix0, ix1]);
|
let message = Message::new(vec![ix0, ix1]);
|
||||||
assert_eq!(FeeCalculator::new(2, 0).calculate_fee(&message), 4);
|
assert_eq!(FeeCalculator::new(2).calculate_fee(&message), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fee_calculator_derived_default() {
|
fn test_fee_rate_governor_derived_default() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
||||||
let f0 = FeeCalculator::default();
|
let f0 = FeeRateGovernor::default();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
f0.target_signatures_per_slot,
|
f0.target_signatures_per_slot,
|
||||||
DEFAULT_TARGET_SIGNATURES_PER_SLOT
|
DEFAULT_TARGET_SIGNATURES_PER_SLOT
|
||||||
@ -185,7 +218,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(f0.lamports_per_signature, 0);
|
assert_eq!(f0.lamports_per_signature, 0);
|
||||||
|
|
||||||
let f1 = FeeCalculator::new_derived(&f0, DEFAULT_TARGET_SIGNATURES_PER_SLOT);
|
let f1 = FeeRateGovernor::new_derived(&f0, DEFAULT_TARGET_SIGNATURES_PER_SLOT);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
f1.target_signatures_per_slot,
|
f1.target_signatures_per_slot,
|
||||||
DEFAULT_TARGET_SIGNATURES_PER_SLOT
|
DEFAULT_TARGET_SIGNATURES_PER_SLOT
|
||||||
@ -201,20 +234,20 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fee_calculator_derived_adjust() {
|
fn test_fee_rate_governor_derived_adjust() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
||||||
let mut f = FeeCalculator::default();
|
let mut f = FeeRateGovernor::default();
|
||||||
f.target_lamports_per_signature = 100;
|
f.target_lamports_per_signature = 100;
|
||||||
f.target_signatures_per_slot = 100;
|
f.target_signatures_per_slot = 100;
|
||||||
f = FeeCalculator::new_derived(&f, 0);
|
f = FeeRateGovernor::new_derived(&f, 0);
|
||||||
|
|
||||||
// Ramp fees up
|
// Ramp fees up
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
loop {
|
loop {
|
||||||
let last_lamports_per_signature = f.lamports_per_signature;
|
let last_lamports_per_signature = f.lamports_per_signature;
|
||||||
|
|
||||||
f = FeeCalculator::new_derived(&f, std::usize::MAX);
|
f = FeeRateGovernor::new_derived(&f, std::u64::MAX);
|
||||||
info!("[up] f.lamports_per_signature={}", f.lamports_per_signature);
|
info!("[up] f.lamports_per_signature={}", f.lamports_per_signature);
|
||||||
|
|
||||||
// some maximum target reached
|
// some maximum target reached
|
||||||
@ -230,7 +263,7 @@ mod tests {
|
|||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
loop {
|
loop {
|
||||||
let last_lamports_per_signature = f.lamports_per_signature;
|
let last_lamports_per_signature = f.lamports_per_signature;
|
||||||
f = FeeCalculator::new_derived(&f, 0);
|
f = FeeRateGovernor::new_derived(&f, 0);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"[down] f.lamports_per_signature={}",
|
"[down] f.lamports_per_signature={}",
|
||||||
@ -250,7 +283,7 @@ mod tests {
|
|||||||
// Arrive at target rate
|
// Arrive at target rate
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while f.lamports_per_signature != f.target_lamports_per_signature {
|
while f.lamports_per_signature != f.target_lamports_per_signature {
|
||||||
f = FeeCalculator::new_derived(&f, f.target_signatures_per_slot);
|
f = FeeRateGovernor::new_derived(&f, f.target_signatures_per_slot);
|
||||||
info!(
|
info!(
|
||||||
"[target] f.lamports_per_signature={}",
|
"[target] f.lamports_per_signature={}",
|
||||||
f.lamports_per_signature
|
f.lamports_per_signature
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
account::Account,
|
account::Account,
|
||||||
clock::{UnixTimestamp, DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT},
|
clock::{UnixTimestamp, DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT},
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeRateGovernor,
|
||||||
hash::{hash, Hash},
|
hash::{hash, Hash},
|
||||||
inflation::Inflation,
|
inflation::Inflation,
|
||||||
native_token::lamports_to_sol,
|
native_token::lamports_to_sol,
|
||||||
@ -49,7 +49,7 @@ pub struct GenesisConfig {
|
|||||||
/// network speed configuration
|
/// network speed configuration
|
||||||
pub poh_config: PohConfig,
|
pub poh_config: PohConfig,
|
||||||
/// transaction fee config
|
/// transaction fee config
|
||||||
pub fee_calculator: FeeCalculator,
|
pub fee_rate_governor: FeeRateGovernor,
|
||||||
/// rent config
|
/// rent config
|
||||||
pub rent: Rent,
|
pub rent: Rent,
|
||||||
/// inflation config
|
/// inflation config
|
||||||
@ -89,7 +89,7 @@ impl Default for GenesisConfig {
|
|||||||
slots_per_segment: DEFAULT_SLOTS_PER_SEGMENT,
|
slots_per_segment: DEFAULT_SLOTS_PER_SEGMENT,
|
||||||
poh_config: PohConfig::default(),
|
poh_config: PohConfig::default(),
|
||||||
inflation: Inflation::default(),
|
inflation: Inflation::default(),
|
||||||
fee_calculator: FeeCalculator::default(),
|
fee_rate_governor: FeeRateGovernor::default(),
|
||||||
rent: Rent::default(),
|
rent: Rent::default(),
|
||||||
epoch_schedule: EpochSchedule::default(),
|
epoch_schedule: EpochSchedule::default(),
|
||||||
operating_mode: OperatingMode::Development,
|
operating_mode: OperatingMode::Development,
|
||||||
@ -205,7 +205,7 @@ impl fmt::Display for GenesisConfig {
|
|||||||
"dis"
|
"dis"
|
||||||
},
|
},
|
||||||
self.rent,
|
self.rent,
|
||||||
self.fee_calculator,
|
self.fee_rate_governor,
|
||||||
lamports_to_sol(
|
lamports_to_sol(
|
||||||
self.accounts
|
self.accounts
|
||||||
.iter()
|
.iter()
|
||||||
|
Reference in New Issue
Block a user