Skip to content

Commit

Permalink
Only check rent-state of writable tx accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
CriesofCarrots committed Jan 6, 2022
1 parent 8f33d3e commit c02d320
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 33 deletions.
22 changes: 22 additions & 0 deletions runtime/src/account_rent_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use {
native_loader,
rent::Rent,
sysvar,
transaction::{Result, TransactionError},
transaction_context::TransactionContext,
},
};

Expand Down Expand Up @@ -52,6 +54,26 @@ pub(crate) fn submit_rent_state_metrics(pre_rent_state: &RentState, post_rent_st
}
}

pub(crate) fn check_rent_state(
pre_rent_state: Option<&RentState>,
post_rent_state: Option<&RentState>,
transaction_context: &TransactionContext,
index: usize,
) -> Result<()> {
if let Some((pre_rent_state, post_rent_state)) = pre_rent_state.zip(post_rent_state) {
if !post_rent_state.transition_allowed_from(pre_rent_state) {
debug!(
"Account {:?} not rent exempt, state {:?}",
transaction_context.get_key_of_account_at_index(index),
transaction_context.get_account_at_index(index).borrow(),
);
submit_rent_state_metrics(pre_rent_state, post_rent_state);
return Err(TransactionError::InvalidRentPayingAccount);
}
}
Ok(())
}

#[cfg(test)]
mod tests {
use {super::*, solana_sdk::pubkey::Pubkey};
Expand Down
21 changes: 11 additions & 10 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3589,7 +3589,8 @@ impl Bank {
compute_budget.max_invoke_depth.saturating_add(1),
);

let pre_account_state_info = self.get_transaction_account_state_info(&transaction_context);
let pre_account_state_info =
self.get_transaction_account_state_info(&transaction_context, tx.message());

let instruction_recorder = if enable_cpi_recording {
Some(InstructionRecorder::new_ref(
Expand Down Expand Up @@ -3635,7 +3636,8 @@ impl Bank {
.and_then(|instruction_recorder| Rc::try_unwrap(instruction_recorder).ok())
.map(|instruction_recorder| instruction_recorder.into_inner().deconstruct());

let post_account_state_info = self.get_transaction_account_state_info(&transaction_context);
let post_account_state_info =
self.get_transaction_account_state_info(&transaction_context, tx.message());

if self
.feature_set
Expand Down Expand Up @@ -15345,21 +15347,20 @@ pub(crate) mod tests {
}

fn mock_transfer_process_instruction(
first_instruction_account: usize,
_first_instruction_account: usize,
data: &[u8],
invoke_context: &mut InvokeContext,
) -> result::Result<(), InstructionError> {
let keyed_accounts = invoke_context.get_keyed_accounts()?;
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context.get_current_instruction_context()?;
if let Ok(instruction) = bincode::deserialize(data) {
match instruction {
MockTransferInstruction::Transfer(amount) => {
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?
.account
.borrow_mut()
instruction_context
.try_borrow_instruction_account(transaction_context, 1)?
.checked_sub_lamports(amount)?;
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
.account
.borrow_mut()
instruction_context
.try_borrow_instruction_account(transaction_context, 2)?
.checked_add_lamports(amount)?;
Ok(())
}
Expand Down
44 changes: 21 additions & 23 deletions runtime/src/bank/transaction_account_state_info.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
use {
crate::{
account_rent_state::{submit_rent_state_metrics, RentState},
account_rent_state::{check_rent_state, RentState},
bank::Bank,
message_processor::ProcessedMessageInfo,
},
log::debug,
solana_sdk::{
transaction::{Result, TransactionError},
transaction_context::TransactionContext,
message::SanitizedMessage, transaction::Result, transaction_context::TransactionContext,
},
};

pub(crate) struct TransactionAccountStateInfo {
rent_state: RentState,
rent_state: Option<RentState>, // None: readonly account
}

impl Bank {
pub(crate) fn get_transaction_account_state_info(
&self,
transaction_context: &TransactionContext,
message: &SanitizedMessage,
) -> Vec<TransactionAccountStateInfo> {
(0..transaction_context.get_number_of_accounts())
.map(|i| {
let account = transaction_context.get_account_at_index(i).borrow();
TransactionAccountStateInfo {
rent_state: RentState::from_account(&account, &self.rent_collector().rent),
}
let rent_state = if message.is_writable(i) {
let account = transaction_context.get_account_at_index(i).borrow();
Some(RentState::from_account(
&account,
&self.rent_collector().rent,
))
} else {
None
};
TransactionAccountStateInfo { rent_state }
})
.collect()
}
Expand All @@ -40,20 +45,13 @@ impl Bank {
for (i, (pre_state_info, post_state_info)) in
pre_state_infos.iter().zip(post_state_infos).enumerate()
{
if !post_state_info
.rent_state
.transition_allowed_from(&pre_state_info.rent_state)
{
debug!(
"Account {:?} not rent exempt, state {:?}",
transaction_context.get_key_of_account_at_index(i),
transaction_context.get_account_at_index(i).borrow(),
);
submit_rent_state_metrics(
&pre_state_info.rent_state,
&post_state_info.rent_state,
);
*process_result = Err(TransactionError::InvalidRentPayingAccount)
if let Err(err) = check_rent_state(
pre_state_info.rent_state.as_ref(),
post_state_info.rent_state.as_ref(),
transaction_context,
i,
) {
*process_result = Err(err)
}
}
}
Expand Down

0 comments on commit c02d320

Please sign in to comment.