Rent tangential stuff (#5910)

* rename rent.rs to rent_calculator.rs

* add rent sysvar

* integrate rent_calculator with bank

* rent_calculator integration with genesis

* add test for rent sysvar
This commit is contained in:
Parth 2019-09-17 17:12:55 +05:30 committed by GitHub
parent b31d334ef4
commit d63518a835
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 157 additions and 30 deletions

View File

@ -11,7 +11,7 @@ use solana_sdk::genesis_block::Builder;
use solana_sdk::hash::{hash, Hash};
use solana_sdk::poh_config::PohConfig;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::rent::Rent;
use solana_sdk::rent_calculator::RentCalculator;
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
use solana_sdk::system_program;
use solana_sdk::timing;
@ -70,7 +70,11 @@ fn main() -> Result<(), Box<dyn error::Error>> {
let default_target_lamports_per_signature = &FeeCalculator::default()
.target_lamports_per_signature
.to_string();
let default_lamports_per_byte_year = &Rent::default().lamports_per_byte_year.to_string();
let default_lamports_per_byte_year =
&RentCalculator::default().lamports_per_byte_year.to_string();
let default_rent_exemption_threshold =
&RentCalculator::default().exemption_threshold.to_string();
let default_rent_burn_percentage = &RentCalculator::default().burn_percent.to_string();
let default_target_signatures_per_slot = &FeeCalculator::default()
.target_signatures_per_slot
.to_string();
@ -184,6 +188,25 @@ fn main() -> Result<(), Box<dyn error::Error>> {
for accounts with data.",
),
)
.arg(
Arg::with_name("rent_exemption_threshold")
.long("rent-exemption-threshold")
.value_name("NUMBER")
.takes_value(true)
.default_value(default_rent_exemption_threshold)
.help(
"amount of time (in years) the balance has to include rent for \
to qualify as rent exempted account.",
),
)
.arg(
Arg::with_name("rent_burn_percentage")
.long("rent-burn-percentage")
.value_name("NUMBER")
.takes_value(true)
.default_value(default_rent_burn_percentage)
.help("amount of rent to burn, as a fraction of std::u8::MAX."),
)
.arg(
Arg::with_name("target_signatures_per_slot")
.long("target-signatures-per-slot")
@ -315,6 +338,13 @@ fn main() -> Result<(), Box<dyn error::Error>> {
value_t_or_exit!(matches, "target_signatures_per_slot", usize);
builder = builder.fee_calculator(FeeCalculator::new_derived(&fee_calculator, 0));
let rent_calculator = RentCalculator {
lamports_per_byte_year: value_t_or_exit!(matches, "lamports_per_byte_year", u64),
exemption_threshold: value_t_or_exit!(matches, "rent_exemption_threshold", f64),
burn_percent: value_t_or_exit!(matches, "rent_burn_percentage", u8),
};
builder = builder.rent_calculator(rent_calculator);
let mut poh_config = PohConfig::default();
poh_config.target_tick_duration =
Duration::from_millis(value_t_or_exit!(matches, "target_tick_duration", u64));

View File

@ -7,8 +7,9 @@ use solana_sdk::{
entrypoint,
entrypoint::SUCCESS,
pubkey::Pubkey,
rent_calculator,
sysvar::{
clock::Clock, fees::Fees, rewards::Rewards, slot_hashes::SlotHashes,
clock::Clock, fees::Fees, rent::Rent, rewards::Rewards, slot_hashes::SlotHashes,
stake_history::StakeHistory,
},
};
@ -39,5 +40,16 @@ fn process_instruction(_program_id: &Pubkey, accounts: &mut [AccountInfo], _data
let stake_history = StakeHistory::from_account_info(&accounts[6]).unwrap();
assert_eq!(stake_history.len(), 1);
let rent = Rent::from_account_info(&accounts[7]).unwrap();
assert_eq!(
rent.rent_calculator.due(
rent_calculator::DEFAULT_LAMPORTS_PER_BYTE_YEAR
* rent_calculator::DEFAULT_EXEMPTION_THRESHOLD as u64,
1,
1.0
),
(0, true)
);
SUCCESS
}

View File

@ -83,7 +83,7 @@ mod bpf {
use solana_sdk::instruction::{AccountMeta, Instruction};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::sysvar::{clock, fees, rewards, slot_hashes, stake_history};
use solana_sdk::sysvar::{clock, fees, rewards, slot_hashes, stake_history, rent};
use std::io::Read;
use std::sync::Arc;
@ -132,6 +132,7 @@ mod bpf {
AccountMeta::new(rewards::id(), false),
AccountMeta::new(slot_hashes::id(), false),
AccountMeta::new(stake_history::id(), false),
AccountMeta::new(rent::id(), false)
];
let instruction = Instruction::new(program_id, &1u8, account_metas);
let result = bank_client.send_instruction(&mint_keypair, instruction);

View File

@ -74,9 +74,9 @@ fn initialize_account(vote_pubkey: &Pubkey, node_pubkey: &Pubkey, commission: u8
}
pub fn minimum_balance() -> u64 {
let rent = solana_sdk::rent::Rent::default();
let rent_calculator = solana_sdk::rent_calculator::RentCalculator::default();
rent.minimum_balance(VoteState::size_of())
rent_calculator.minimum_balance(VoteState::size_of())
}
pub fn create_account(
@ -279,8 +279,8 @@ mod tests {
#[test]
fn test_minimum_balance() {
let rent = solana_sdk::rent::Rent::default();
let minimum_balance = rent.minimum_balance(VoteState::size_of());
let rent_calculator = solana_sdk::rent_calculator::RentCalculator::default();
let minimum_balance = rent_calculator.minimum_balance(VoteState::size_of());
// vote state cheaper than "my $0.02" ;)
assert!(minimum_balance as f64 / 2f64.powf(34.0) < 0.02)
}

View File

@ -41,7 +41,7 @@ use solana_sdk::{
signature::{Keypair, Signature},
system_transaction,
sysvar::{
clock, fees, rewards,
clock, fees, rent, rewards,
slot_hashes::{self, SlotHashes},
stake_history,
},
@ -354,6 +354,7 @@ impl Bank {
new.update_stake_history(Some(parent.epoch()));
new.update_clock();
new.update_fees();
new.update_rent();
new
}
@ -426,6 +427,13 @@ impl Bank {
self.store_account(&fees::id(), &fees::create_account(1, &self.fee_calculator));
}
fn update_rent(&self) {
self.store_account(
&rent::id(),
&rent::create_account(1, &self.rent_collector.rent_calculator),
);
}
fn update_stake_history(&self, epoch: Option<Epoch>) {
if epoch == Some(self.epoch()) {
return;
@ -620,6 +628,14 @@ impl Bank {
self.inflation = genesis_block.inflation;
let rent_calculator = genesis_block.rent_calculator;
self.rent_collector = RentCollector::new(
self.epoch,
&self.epoch_schedule,
self.slots_per_year,
&rent_calculator,
);
// Add additional native programs specified in the genesis block
for (name, program_id) in &genesis_block.native_instruction_processors {
self.register_native_instruction_processor(name, program_id);

View File

@ -1,13 +1,13 @@
//! calculate and collect rent from Accounts
use crate::epoch_schedule::EpochSchedule;
use solana_sdk::{account::Account, clock::Epoch, rent::Rent};
use solana_sdk::{account::Account, clock::Epoch, rent_calculator::RentCalculator};
#[derive(Default, Serialize, Deserialize, Clone)]
pub struct RentCollector {
pub epoch: Epoch,
pub epoch_schedule: EpochSchedule,
pub slots_per_year: f64,
pub rent: Rent,
pub rent_calculator: RentCalculator,
}
impl RentCollector {
@ -15,13 +15,13 @@ impl RentCollector {
epoch: Epoch,
epoch_schedule: &EpochSchedule,
slots_per_year: f64,
rent: &Rent,
rent_calculator: &RentCalculator,
) -> Self {
Self {
epoch,
epoch_schedule: *epoch_schedule,
slots_per_year,
rent: *rent,
rent_calculator: *rent_calculator,
}
}
@ -42,7 +42,7 @@ impl RentCollector {
.map(|epoch| self.epoch_schedule.get_slots_in_epoch(epoch + 1))
.sum();
let (rent_due, exempt) = self.rent.due(
let (rent_due, exempt) = self.rent_calculator.due(
account.lamports,
account.data.len(),
slots_elapsed as f64 / self.slots_per_year,

View File

@ -7,7 +7,7 @@ use crate::hash::{hash, Hash};
use crate::inflation::Inflation;
use crate::poh_config::PohConfig;
use crate::pubkey::Pubkey;
use crate::rent::Rent;
use crate::rent_calculator::RentCalculator;
use crate::signature::{Keypair, KeypairUtil};
use crate::system_program::{self, solana_system_program};
use bincode::{deserialize, serialize};
@ -28,8 +28,8 @@ pub struct GenesisBlock {
pub slots_per_segment: u64,
pub poh_config: PohConfig,
pub fee_calculator: FeeCalculator,
pub rent_calculator: RentCalculator,
pub inflation: Inflation,
pub rent: Rent,
}
// useful for basic tests
@ -61,7 +61,7 @@ impl Default for GenesisBlock {
poh_config: PohConfig::default(),
inflation: Inflation::default(),
fee_calculator: FeeCalculator::default(),
rent: Rent::default(),
rent_calculator: RentCalculator::default(),
}
}
}
@ -147,6 +147,10 @@ impl Builder {
self.genesis_block.inflation = inflation;
self
}
pub fn rent_calculator(mut self, rent_calculator: RentCalculator) -> Self {
self.genesis_block.rent_calculator = rent_calculator;
self
}
}
impl GenesisBlock {

View File

@ -13,7 +13,7 @@ pub mod native_loader;
pub mod packet;
pub mod poh_config;
pub mod pubkey;
pub mod rent;
pub mod rent_calculator;
pub mod rpc_port;
pub mod short_vec;
pub mod system_instruction;

View File

@ -1,7 +1,7 @@
//! configuration for network rent
#[derive(Serialize, Deserialize, PartialEq, Clone, Copy, Debug)]
pub struct Rent {
pub struct RentCalculator {
/// Rental rate
pub lamports_per_byte_year: u64,
@ -25,7 +25,7 @@ pub const DEFAULT_EXEMPTION_THRESHOLD: f64 = 2.0;
/// default amount of rent to burn, as a fraction of std::u8::MAX
pub const DEFAULT_BURN_PERCENT: u8 = ((50usize * std::u8::MAX as usize) / 100usize) as u8;
impl Default for Rent {
impl Default for RentCalculator {
fn default() -> Self {
Self {
lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE_YEAR,
@ -35,7 +35,7 @@ impl Default for Rent {
}
}
impl Rent {
impl RentCalculator {
/// minimum balance due for a given size Account::data.len()
pub fn minimum_balance(&self, data_len: usize) -> u64 {
let bytes = data_len as u64;
@ -66,17 +66,17 @@ mod tests {
#[test]
fn test_due() {
let rent = Rent::default();
let rent_calculator = RentCalculator::default();
assert_eq!(
rent.due(0, 1, 1.0),
rent_calculator.due(0, 1, 1.0),
(
DEFAULT_LAMPORTS_PER_BYTE_YEAR,
DEFAULT_LAMPORTS_PER_BYTE_YEAR == 0
)
);
assert_eq!(
rent.due(
rent_calculator.due(
DEFAULT_LAMPORTS_PER_BYTE_YEAR * DEFAULT_EXEMPTION_THRESHOLD as u64,
1,
1.0
@ -94,21 +94,21 @@ mod tests {
// const SLOTS_PER_YEAR: f64 =
// SECONDS_PER_YEAR / (DEFAULT_TICKS_PER_SLOT as f64 / DEFAULT_TICKS_PER_SECOND as f64);
//
// let rent = Rent::default();
// let rent_calculator = RentCalculator::default();
//
// eprintln();
// // lamports charged per byte per slot at $1/MByear, rent per slot is zero
// eprintln(
// "{} lamports per byte-slot, rent.due(): {}",
// "{} lamports per byte-slot, rent_calculator.due(): {}",
// (1.0 / SLOTS_PER_YEAR) * DEFAULT_LAMPORTS_PER_BYTE_YEAR as f64,
// rent.due(0, 1, 1.0 / SLOTS_PER_YEAR).0,
// rent_calculator.due(0, 1, 1.0 / SLOTS_PER_YEAR).0,
// );
// // lamports charged per byte per _epoch_ starts to have some significant digits
// eprintln(
// "{} lamports per byte-epoch, rent.due(): {}",
// "{} lamports per byte-epoch, rent_calculator.due(): {}",
// (1.0 / SLOTS_PER_YEAR)
// * (DEFAULT_LAMPORTS_PER_BYTE_YEAR * DEFAULT_SLOTS_PER_EPOCH) as f64,
// rent.due(
// rent_calculator.due(
// 0,
// 1,
// (1.0 / SLOTS_PER_YEAR) * DEFAULT_SLOTS_PER_EPOCH as f64
@ -119,7 +119,7 @@ mod tests {
// eprintln(
// "stake_history: {}kB == {} lamports per epoch",
// crate::sysvar::stake_history::StakeHistory::size_of() / 1024,
// rent.due(
// rent_calculator.due(
// 0,
// crate::sysvar::stake_history::StakeHistory::size_of(),
// (1.0 / SLOTS_PER_YEAR) * DEFAULT_SLOTS_PER_EPOCH as f64

View File

@ -4,6 +4,7 @@ use crate::pubkey::Pubkey;
pub mod clock;
pub mod fees;
pub mod rent;
pub mod rewards;
pub mod slot_hashes;
pub mod stake_history;

63
sdk/src/sysvar/rent.rs Normal file
View File

@ -0,0 +1,63 @@
//! This account contains the current cluster rent
//!
use crate::account::Account;
use crate::account_info::AccountInfo;
use crate::rent_calculator::RentCalculator;
use crate::sysvar;
use bincode::serialized_size;
/// rent account pubkey
const ID: [u8; 32] = [
6, 167, 213, 23, 25, 44, 92, 81, 33, 140, 201, 76, 61, 74, 241, 127, 88, 218, 238, 8, 155, 161,
253, 68, 227, 219, 217, 138, 0, 0, 0, 0,
];
crate::solana_name_id!(ID, "SysvarRent111111111111111111111111111111111");
#[repr(C)]
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Rent {
pub rent_calculator: RentCalculator,
}
impl Rent {
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn size_of() -> usize {
serialized_size(&Rent::default()).unwrap() as usize
}
}
pub fn create_account(lamports: u64, rent_calculator: &RentCalculator) -> Account {
Account::new_data(
lamports,
&Rent {
rent_calculator: *rent_calculator,
},
&sysvar::id(),
)
.unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fees_create_account() {
let lamports = 42;
let account = create_account(lamports, &RentCalculator::default());
let rent = Rent::from_account(&account).unwrap();
assert_eq!(rent.rent_calculator, RentCalculator::default());
}
}