runtime: add rent debit charges to block metadata

This commit is contained in:
Trent Nelson 2021-05-25 23:11:26 -06:00 committed by mergify[bot]
parent e9bc1c6b07
commit 97eab7edf9
2 changed files with 62 additions and 15 deletions

View File

@ -5,7 +5,8 @@ use crate::{
accounts_index::{AccountSecondaryIndexes, IndexKey}, accounts_index::{AccountSecondaryIndexes, IndexKey},
ancestors::Ancestors, ancestors::Ancestors,
bank::{ bank::{
NonceRollbackFull, NonceRollbackInfo, TransactionCheckResult, TransactionExecutionResult, NonceRollbackFull, NonceRollbackInfo, RentDebits, TransactionCheckResult,
TransactionExecutionResult,
}, },
blockhash_queue::BlockhashQueue, blockhash_queue::BlockhashQueue,
rent_collector::RentCollector, rent_collector::RentCollector,
@ -99,12 +100,14 @@ pub type TransactionAccounts = Vec<AccountSharedData>;
pub type TransactionAccountDeps = Vec<(Pubkey, AccountSharedData)>; pub type TransactionAccountDeps = Vec<(Pubkey, AccountSharedData)>;
pub type TransactionRent = u64; pub type TransactionRent = u64;
pub type TransactionLoaders = Vec<Vec<(Pubkey, AccountSharedData)>>; pub type TransactionLoaders = Vec<Vec<(Pubkey, AccountSharedData)>>;
pub type TransactionRentDebits = RentDebits;
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Clone)]
pub struct LoadedTransaction { pub struct LoadedTransaction {
pub accounts: TransactionAccounts, pub accounts: TransactionAccounts,
pub account_deps: TransactionAccountDeps, pub account_deps: TransactionAccountDeps,
pub loaders: TransactionLoaders, pub loaders: TransactionLoaders,
pub rent: TransactionRent, pub rent: TransactionRent,
pub rent_debits: TransactionRentDebits,
} }
pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceRollbackFull>); pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceRollbackFull>);
@ -206,6 +209,7 @@ impl Accounts {
let demote_sysvar_write_locks = let demote_sysvar_write_locks =
feature_set.is_active(&feature_set::demote_sysvar_write_locks::id()); feature_set.is_active(&feature_set::demote_sysvar_write_locks::id());
let mut key_check = MessageProgramIdsCache::new(&message); let mut key_check = MessageProgramIdsCache::new(&message);
let mut rent_debits = RentDebits::default();
for (i, key) in message.account_keys.iter().enumerate() { for (i, key) in message.account_keys.iter().enumerate() {
let account = if key_check.is_non_loader_key(key, i) { let account = if key_check.is_non_loader_key(key, i) {
if payer_index.is_none() { if payer_index.is_none() {
@ -258,6 +262,8 @@ impl Accounts {
} }
tx_rent += rent; tx_rent += rent;
rent_debits.push(key, rent, account.lamports());
account account
} }
} else { } else {
@ -319,6 +325,7 @@ impl Accounts {
account_deps, account_deps,
loaders, loaders,
rent: tx_rent, rent: tx_rent,
rent_debits,
}) })
} }
} }
@ -995,8 +1002,11 @@ impl Accounts {
} }
} }
if account.rent_epoch() == INITIAL_RENT_EPOCH { if account.rent_epoch() == INITIAL_RENT_EPOCH {
loaded_transaction.rent += let rent = rent_collector.collect_from_created_account(&key, account);
rent_collector.collect_from_created_account(&key, account); loaded_transaction.rent += rent;
loaded_transaction
.rent_debits
.push(key, rent, account.lamports());
} }
accounts.push((key, &*account)); accounts.push((key, &*account));
} }
@ -1968,6 +1978,7 @@ mod tests {
account_deps: vec![], account_deps: vec![],
loaders: transaction_loaders0, loaders: transaction_loaders0,
rent: transaction_rent0, rent: transaction_rent0,
rent_debits: RentDebits::default(),
}), }),
None, None,
); );
@ -1981,6 +1992,7 @@ mod tests {
account_deps: vec![], account_deps: vec![],
loaders: transaction_loaders1, loaders: transaction_loaders1,
rent: transaction_rent1, rent: transaction_rent1,
rent_debits: RentDebits::default(),
}), }),
None, None,
); );
@ -2363,6 +2375,7 @@ mod tests {
account_deps: vec![], account_deps: vec![],
loaders: transaction_loaders, loaders: transaction_loaders,
rent: transaction_rent, rent: transaction_rent,
rent_debits: RentDebits::default(),
}), }),
nonce_rollback, nonce_rollback,
); );
@ -2481,6 +2494,7 @@ mod tests {
account_deps: vec![], account_deps: vec![],
loaders: transaction_loaders, loaders: transaction_loaders,
rent: transaction_rent, rent: transaction_rent,
rent_debits: RentDebits::default(),
}), }),
nonce_rollback, nonce_rollback,
); );

View File

@ -131,6 +131,27 @@ pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0;
pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5; pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5;
#[derive(Clone, Debug, Default, PartialEq)]
pub struct RentDebits(pub Vec<(Pubkey, RewardInfo)>);
impl RentDebits {
pub fn push(&mut self, account: &Pubkey, rent: u64, post_balance: u64) {
if rent != 0 {
let rent_debit = i64::try_from(rent).ok().and_then(|r| r.checked_neg());
if let Some(rent_debit) = rent_debit {
let reward_info = RewardInfo {
reward_type: RewardType::Rent,
lamports: rent_debit,
post_balance,
};
self.0.push((*account, reward_info));
} else {
warn!("out of range rent debit from {}: {}", account, rent);
}
}
}
}
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ExecuteTimings { pub struct ExecuteTimings {
pub check_us: u64, pub check_us: u64,
@ -3547,18 +3568,22 @@ impl Bank {
fn collect_rent( fn collect_rent(
&self, &self,
res: &[TransactionExecutionResult], res: &[TransactionExecutionResult],
loaded_accounts: &[TransactionLoadResult], loaded_accounts: &mut [TransactionLoadResult],
) { ) {
let mut collected_rent: u64 = 0; let mut collected_rent: u64 = 0;
for (i, (raccs, _nonce_rollback)) in loaded_accounts.iter().enumerate() { for (i, (raccs, _nonce_rollback)) in loaded_accounts.iter_mut().enumerate() {
let (res, _nonce_rollback) = &res[i]; let (res, _nonce_rollback) = &res[i];
if res.is_err() || raccs.is_err() { if res.is_err() || raccs.is_err() {
continue; continue;
} }
let loaded_transaction = raccs.as_ref().unwrap(); let loaded_transaction = raccs.as_mut().unwrap();
collected_rent += loaded_transaction.rent; collected_rent += loaded_transaction.rent;
self.rewards
.write()
.unwrap()
.append(&mut loaded_transaction.rent_debits.0);
} }
self.collected_rent.fetch_add(collected_rent, Relaxed); self.collected_rent.fetch_add(collected_rent, Relaxed);
@ -3630,19 +3655,23 @@ impl Bank {
let account_count = accounts.len(); let account_count = accounts.len();
// parallelize? // parallelize?
let mut rent = 0; let mut total_rent = 0;
let mut rent_debits = RentDebits::default();
for (pubkey, mut account) in accounts { for (pubkey, mut account) in accounts {
rent += self let rent = self
.rent_collector .rent_collector
.collect_from_existing_account(&pubkey, &mut account); .collect_from_existing_account(&pubkey, &mut account);
total_rent += rent;
// Store all of them unconditionally to purge old AppendVec, // Store all of them unconditionally to purge old AppendVec,
// even if collected rent is 0 (= not updated). // even if collected rent is 0 (= not updated).
// Also, there's another subtle side-effect from this: this // Also, there's another subtle side-effect from this: this
// ensures we verify the whole on-chain state (= all accounts) // ensures we verify the whole on-chain state (= all accounts)
// via the account delta hash slowly once per an epoch. // via the account delta hash slowly once per an epoch.
self.store_account(&pubkey, &account); self.store_account(&pubkey, &account);
rent_debits.push(&pubkey, rent, account.lamports());
} }
self.collected_rent.fetch_add(rent, Relaxed); self.collected_rent.fetch_add(total_rent, Relaxed);
self.rewards.write().unwrap().append(&mut rent_debits.0);
datapoint_info!("collect_rent_eagerly", ("accounts", account_count, i64)); datapoint_info!("collect_rent_eagerly", ("accounts", account_count, i64));
} }
@ -6093,13 +6122,17 @@ pub(crate) mod tests {
.unwrap() .unwrap()
.iter() .iter()
.map(|(address, reward)| { .map(|(address, reward)| {
assert_eq!(reward.reward_type, RewardType::Rent); if reward.lamports > 0 {
if *address == validator_2_pubkey { assert_eq!(reward.reward_type, RewardType::Rent);
assert_eq!(reward.post_balance, validator_2_portion + 42 - tweak_2); if *address == validator_2_pubkey {
} else if *address == validator_3_pubkey { assert_eq!(reward.post_balance, validator_2_portion + 42 - tweak_2);
assert_eq!(reward.post_balance, validator_3_portion + 42); } else if *address == validator_3_pubkey {
assert_eq!(reward.post_balance, validator_3_portion + 42);
}
reward.lamports as u64
} else {
0
} }
reward.lamports as u64
}) })
.sum::<u64>() .sum::<u64>()
); );