2019-08-23 14:04:53 -07:00
|
|
|
//! calculate and collect rent from Accounts
|
2019-11-18 12:01:27 -08:00
|
|
|
use solana_sdk::{
|
2020-04-30 22:04:08 -07:00
|
|
|
account::Account, clock::Epoch, epoch_schedule::EpochSchedule, incinerator, pubkey::Pubkey,
|
|
|
|
rent::Rent, sysvar,
|
2019-11-18 12:01:27 -08:00
|
|
|
};
|
2019-08-23 14:04:53 -07:00
|
|
|
|
|
|
|
#[derive(Default, Serialize, Deserialize, Clone)]
|
|
|
|
pub struct RentCollector {
|
|
|
|
pub epoch: Epoch,
|
|
|
|
pub epoch_schedule: EpochSchedule,
|
|
|
|
pub slots_per_year: f64,
|
2019-10-30 16:25:12 -07:00
|
|
|
pub rent: Rent,
|
2019-08-23 14:04:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl RentCollector {
|
|
|
|
pub fn new(
|
|
|
|
epoch: Epoch,
|
|
|
|
epoch_schedule: &EpochSchedule,
|
|
|
|
slots_per_year: f64,
|
2019-10-30 16:25:12 -07:00
|
|
|
rent: &Rent,
|
2019-08-23 14:04:53 -07:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
epoch,
|
|
|
|
epoch_schedule: *epoch_schedule,
|
|
|
|
slots_per_year,
|
2019-10-30 16:25:12 -07:00
|
|
|
rent: *rent,
|
2019-08-23 14:04:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clone_with_epoch(&self, epoch: Epoch) -> Self {
|
|
|
|
Self {
|
|
|
|
epoch,
|
|
|
|
..self.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// updates this account's lamports and status and returns
|
|
|
|
// the account rent collected, if any
|
|
|
|
//
|
2020-04-30 22:04:08 -07:00
|
|
|
pub fn update(&self, address: &Pubkey, account: &mut Account) -> u64 {
|
|
|
|
if account.executable
|
|
|
|
|| account.rent_epoch > self.epoch
|
|
|
|
|| sysvar::check_id(&account.owner)
|
|
|
|
|| *address == incinerator::id()
|
2020-03-27 08:28:18 -07:00
|
|
|
{
|
2019-11-13 21:26:49 -08:00
|
|
|
0
|
2019-08-23 14:04:53 -07:00
|
|
|
} else {
|
|
|
|
let slots_elapsed: u64 = (account.rent_epoch..=self.epoch)
|
|
|
|
.map(|epoch| self.epoch_schedule.get_slots_in_epoch(epoch + 1))
|
|
|
|
.sum();
|
|
|
|
|
2020-06-08 17:38:14 -07:00
|
|
|
// avoid infinite rent in rust 1.45
|
|
|
|
let years_elapsed = if self.slots_per_year != 0.0 {
|
|
|
|
slots_elapsed as f64 / self.slots_per_year
|
|
|
|
} else {
|
|
|
|
0.0
|
|
|
|
};
|
|
|
|
|
|
|
|
let (rent_due, exempt) =
|
|
|
|
self.rent
|
|
|
|
.due(account.lamports, account.data.len(), years_elapsed);
|
2019-08-23 14:04:53 -07:00
|
|
|
|
|
|
|
if exempt || rent_due != 0 {
|
|
|
|
if account.lamports > rent_due {
|
|
|
|
account.rent_epoch = self.epoch + 1;
|
|
|
|
account.lamports -= rent_due;
|
2019-11-13 21:26:49 -08:00
|
|
|
rent_due
|
2019-08-23 14:04:53 -07:00
|
|
|
} else {
|
2019-11-13 21:26:49 -08:00
|
|
|
let rent_charged = account.lamports;
|
|
|
|
*account = Account::default();
|
|
|
|
rent_charged
|
2019-08-23 14:04:53 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// maybe collect rent later, leave account alone
|
2019-11-13 21:26:49 -08:00
|
|
|
0
|
2019-08-23 14:04:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|