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 all 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
2 changes: 1 addition & 1 deletion core/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) {
mut genesis_config,
mint_keypair,
voting_keypair,
} = create_genesis_config_with_leader(10_000, &contact_info.id, 42);
} = create_genesis_config_with_leader(1_000_000, &contact_info.id, 42);
genesis_config
.native_instruction_processors
.push(solana_budget_program!());
Expand Down
5 changes: 3 additions & 2 deletions core/tests/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ fn test_rpc_client() {
);

assert_eq!(client.get_balance(&bob_pubkey).unwrap(), 0);
assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 10000);

assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 1_000_000);

let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap();

Expand All @@ -49,7 +50,7 @@ fn test_rpc_client() {
assert!(confirmed_tx);

assert_eq!(client.get_balance(&bob_pubkey).unwrap(), 20);
assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 9980);
assert_eq!(client.get_balance(&alice.pubkey()).unwrap(), 999980);

server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
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
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
49 changes: 40 additions & 9 deletions sdk/src/rent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ 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 storage over head for calculation of base rent
pub const ACCOUNT_STORAGE_OVERHEAD: u64 = 128;

impl Default for Rent {
fn default() -> Self {
Self {
Expand All @@ -40,7 +43,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
(((ACCOUNT_STORAGE_OVERHEAD + 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 +58,9 @@ impl Rent {
(0, true)
} else {
(
((self.lamports_per_byte_year * data_len as u64) as f64 * years_elapsed) as u64,
((self.lamports_per_byte_year * (data_len as u64 + ACCOUNT_STORAGE_OVERHEAD))
as f64
* years_elapsed) as u64,
false,
)
}
Expand All @@ -74,20 +80,45 @@ mod tests {

#[test]
fn test_due() {
let rent = Rent::default();
let default_rent = Rent::default();

assert_eq!(
rent.due(0, 1, 1.0),
default_rent.due(0, 2, 1.2),
(
DEFAULT_LAMPORTS_PER_BYTE_YEAR,
(((2 + ACCOUNT_STORAGE_OVERHEAD) * DEFAULT_LAMPORTS_PER_BYTE_YEAR) as f64 * 1.2)
as u64,
DEFAULT_LAMPORTS_PER_BYTE_YEAR == 0
)
);
assert_eq!(
rent.due(
DEFAULT_LAMPORTS_PER_BYTE_YEAR * DEFAULT_EXEMPTION_THRESHOLD as u64,
1,
1.0
default_rent.due(
(((2 + ACCOUNT_STORAGE_OVERHEAD) * DEFAULT_LAMPORTS_PER_BYTE_YEAR) as f64
* DEFAULT_EXEMPTION_THRESHOLD) as u64,
2,
1.2
),
(0, true)
);

let mut custom_rent = Rent::default();
custom_rent.lamports_per_byte_year = 5;
custom_rent.exemption_threshold = 2.5;

assert_eq!(
custom_rent.due(0, 2, 1.2),
(
(((2 + ACCOUNT_STORAGE_OVERHEAD) * custom_rent.lamports_per_byte_year) as f64 * 1.2)
as u64,
false
)
);

assert_eq!(
custom_rent.due(
(((2 + ACCOUNT_STORAGE_OVERHEAD) * custom_rent.lamports_per_byte_year) as f64
* custom_rent.exemption_threshold) as u64,
2,
1.2
),
(0, true)
);
Expand Down