solana/runtime/src/rent_collector.rs

67 lines
2.0 KiB
Rust
Raw Normal View History

//! calculate and collect rent from Accounts
use solana_sdk::{
account::Account, clock::Epoch, epoch_schedule::EpochSchedule, 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_calculator: RentCalculator,
}
impl RentCollector {
pub fn new(
epoch: Epoch,
epoch_schedule: &EpochSchedule,
slots_per_year: f64,
rent_calculator: &RentCalculator,
) -> Self {
Self {
epoch,
epoch_schedule: *epoch_schedule,
slots_per_year,
rent_calculator: *rent_calculator,
}
}
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
//
pub fn update(&self, mut account: Account) -> Option<(Account, u64)> {
if account.data.is_empty() || account.rent_epoch > self.epoch {
Some((account, 0))
} else {
let slots_elapsed: u64 = (account.rent_epoch..=self.epoch)
.map(|epoch| self.epoch_schedule.get_slots_in_epoch(epoch + 1))
.sum();
let (rent_due, exempt) = self.rent_calculator.due(
account.lamports,
account.data.len(),
slots_elapsed as f64 / self.slots_per_year,
);
if exempt || rent_due != 0 {
if account.lamports > rent_due {
account.rent_epoch = self.epoch + 1;
account.lamports -= rent_due;
Some((account, rent_due))
} else {
None
}
} else {
// maybe collect rent later, leave account alone
Some((account, 0))
}
}
}
}