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

rent collector improvments #6888

Merged
merged 20 commits into from
Nov 14, 2019
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ pub mod tests {
"lamports": 20,
"data": [],
"executable": false,
"rent_epoch": 0
"rent_epoch": 1
}}]],
"id":1}}
"#,
Expand All @@ -1383,7 +1383,7 @@ pub mod tests {
serde_json::from_str(&expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
assert_eq!(expected, result);
assert_eq!(result, expected);
}

#[test]
Expand Down
15 changes: 14 additions & 1 deletion genesis/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,14 @@ fn main() -> Result<(), Box<dyn error::Error>> {
default_lamports_per_byte_year,
default_rent_exemption_threshold,
default_rent_burn_percentage,
default_base_rent_per_year,
) = {
let rent = Rent::default();
(
&rent.lamports_per_byte_year.to_string(),
&rent.exemption_threshold.to_string(),
&rent.burn_percent.to_string(),
&rent.base_rent_per_year.to_string(),
rob-solana marked this conversation as resolved.
Show resolved Hide resolved
)
};
let default_target_tick_duration =
Expand Down Expand Up @@ -213,7 +215,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.default_value(default_lamports_per_byte_year)
.help(
"The cost in lamports that the cluster will charge per byte per year \
for accounts with data.",
for accounts.",
),
)
.arg(
Expand All @@ -235,6 +237,16 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.default_value(default_rent_burn_percentage)
.help("amount of rent to burn, as a fraction of std::u8::MAX."),
)
.arg(
Arg::with_name("base_rent_per_year")
.long("base-rent-per-year")
.value_name("LAMPORTS")
.takes_value(true)
.default_value(default_base_rent_per_year)
.help(
"The cost in lamports that the cluster will charge as base rent for accounts",
),
)
.arg(
Arg::with_name("target_signatures_per_slot")
.long("target-signatures-per-slot")
Expand Down Expand Up @@ -356,6 +368,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
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),
base_rent_per_year: value_t_or_exit!(matches, "base_rent_per_year", u64),
};

let mut poh_config = PohConfig::default();
Expand Down
5 changes: 4 additions & 1 deletion runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ impl Accounts {
.filter(|key| !message.program_ids().contains(key))
{
let (account, rent) = AccountsDB::load(storage, ancestors, accounts_index, key)
.and_then(|(account, _)| rent_collector.update(account))
.and_then(|(mut account, _)| {
let rent_due = rent_collector.update(&mut account);
Some((account, rent_due))
rob-solana marked this conversation as resolved.
Show resolved Hide resolved
})
.unwrap_or_default();

accounts.push(account);
Expand Down
1 change: 1 addition & 0 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,7 @@ mod tests {
lamports_per_byte_year: 5,
exemption_threshold: 1.2,
burn_percent: 5,
base_rent_per_year: 0,
};

let bank = Bank::new(&genesis_config);
Expand Down
14 changes: 8 additions & 6 deletions runtime/src/rent_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ impl RentCollector {
// updates this account's lamports and status and returns
// the account rent collected, if any
//
pub fn update(&self, mut account: Account) -> Option<(Account, u64)> {
if account.data.is_empty() || account.rent_epoch > self.epoch {
Some((account, 0))
pub fn update(&self, account: &mut Account) -> u64 {
if account.rent_epoch > self.epoch {
0
} else {
let slots_elapsed: u64 = (account.rent_epoch..=self.epoch)
.map(|epoch| self.epoch_schedule.get_slots_in_epoch(epoch + 1))
Expand All @@ -51,13 +51,15 @@ impl RentCollector {
if account.lamports > rent_due {
account.rent_epoch = self.epoch + 1;
account.lamports -= rent_due;
Some((account, rent_due))
rent_due
} else {
None
let rent_charged = account.lamports;
*account = Account::default();
rent_charged
}
} else {
// maybe collect rent later, leave account alone
Some((account, 0))
0
}
}
}
Expand Down
41 changes: 36 additions & 5 deletions sdk/src/rent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub struct Rent {

// What portion of collected rent are to be destroyed, percentage-wise
pub burn_percent: u8,

pub base_rent_per_year: u64,
}

/// default rental rate in lamports/byte-year, based on:
Expand All @@ -26,12 +28,19 @@ 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;

/// default account size (determined by size_of::<Account>())
rob-solana marked this conversation as resolved.
Show resolved Hide resolved
pub const DEFAULT_ACCOUNT_SIZE: u64 = 112;

/// default base rent to be payable per account apart from rent charged on data bytes per year
pub const DEFAULT_BASE_RENT_PER_YEAR: u64 = DEFAULT_ACCOUNT_SIZE * DEFAULT_LAMPORTS_PER_BYTE_YEAR;

impl Default for Rent {
fn default() -> Self {
Self {
lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE_YEAR,
exemption_threshold: DEFAULT_EXEMPTION_THRESHOLD,
burn_percent: DEFAULT_BURN_PERCENT,
base_rent_per_year: DEFAULT_BASE_RENT_PER_YEAR,
}
}
}
Expand All @@ -40,7 +49,8 @@ impl Rent {
/// 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;
bytes * (self.exemption_threshold * self.lamports_per_byte_year as f64) as u64
((self.base_rent_per_year + (bytes * self.lamports_per_byte_year)) as f64
* self.exemption_threshold) as u64
}

/// whether a given balance and data_len would be exempt
Expand All @@ -54,7 +64,8 @@ impl Rent {
(0, true)
} else {
(
((self.lamports_per_byte_year * data_len as u64) as f64 * years_elapsed) as u64,
((self.base_rent_per_year + (self.lamports_per_byte_year * data_len as u64)) as f64
* years_elapsed) as u64,
false,
)
}
Expand All @@ -67,23 +78,43 @@ mod tests {

#[test]
fn test_due() {
let rent = Rent::default();
let rent_with_base_zero = Rent::default();
rob-solana marked this conversation as resolved.
Show resolved Hide resolved

assert_eq!(
rent.due(0, 1, 1.0),
rent_with_base_zero.due(0, 1, 1.0),
(
DEFAULT_LAMPORTS_PER_BYTE_YEAR,
DEFAULT_LAMPORTS_PER_BYTE_YEAR == 0
)
);
assert_eq!(
rent.due(
rent_with_base_zero.due(
DEFAULT_LAMPORTS_PER_BYTE_YEAR * DEFAULT_EXEMPTION_THRESHOLD as u64,
1,
1.0
),
(0, true)
);

let mut rent_with_nonzero_base = Rent::default();
rent_with_nonzero_base.base_rent_per_year = 1;

assert_eq!(
rent_with_nonzero_base.due(0, 1, 1.0),
(
DEFAULT_LAMPORTS_PER_BYTE_YEAR + rent_with_nonzero_base.base_rent_per_year,
false
)
);
assert_eq!(
rent_with_nonzero_base.due(
(DEFAULT_LAMPORTS_PER_BYTE_YEAR + rent_with_nonzero_base.base_rent_per_year)
* DEFAULT_EXEMPTION_THRESHOLD as u64,
1,
1.0
),
(0, true)
);
}

// uncomment me and make my eprintlns macros
Expand Down