Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rent collector improvments #6888

Merged
merged 20 commits into from
Nov 14, 2019
Merged
Show file tree
Hide file tree
Changes from 7 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
38 changes: 33 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,16 @@ 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 base rent
pub const DEFAULT_BASE_RENT_PER_YEAR: u64 = 112 * 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 +46,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 +61,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 +75,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