diff --git a/program-runtime/src/accounts_data_meter.rs b/program-runtime/src/accounts_data_meter.rs index faf2524123ca1f..2c8def20476e30 100644 --- a/program-runtime/src/accounts_data_meter.rs +++ b/program-runtime/src/accounts_data_meter.rs @@ -75,14 +75,20 @@ impl AccountsDataMeter { /// Consume accounts data space, in bytes. If `amount` is positive, we are *increasing* the /// amount of accounts data space used. If `amount` is negative, we are *decreasing* the - /// amount of accounts data space used. + /// amount of accounts data space used. If `amount` is greater than the remaining space, + /// return an error and *do not* consume more accounts data space. pub fn consume(&mut self, amount: i64) -> Result<(), InstructionError> { if amount > self.remaining() as i64 { return Err(InstructionError::AccountsDataBudgetExceeded); } - self.delta = self.delta.saturating_add(amount); + self.consume_unchecked(amount); Ok(()) } + + /// Unconditionally consume accounts data space. Refer to `consume()` for more documentation. + pub fn consume_unchecked(&mut self, amount: i64) { + self.delta = self.delta.saturating_add(amount); + } } #[cfg(test)] diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 33f4eb69d95acd..42aba3e517d5ac 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -500,11 +500,13 @@ impl<'a> InvokeContext<'a> { .checked_add(u128::from(account.lamports())) .ok_or(InstructionError::UnbalancedInstruction)?; + let pre_data_len = pre_account.data().len() as i64; + let post_data_len = account.data().len() as i64; + let data_len_delta = post_data_len.saturating_sub(pre_data_len); if cap_accounts_data_len { - let pre_data_len = pre_account.data().len() as i64; - let post_data_len = account.data().len() as i64; - let data_len_delta = post_data_len.saturating_sub(pre_data_len); self.accounts_data_meter.consume(data_len_delta)?; + } else { + self.accounts_data_meter.consume_unchecked(data_len_delta); } Ok(()) @@ -591,11 +593,13 @@ impl<'a> InvokeContext<'a> { pre_account.update(account.clone()); } + let pre_data_len = pre_account.data().len() as i64; + let post_data_len = account.data().len() as i64; + let data_len_delta = post_data_len.saturating_sub(pre_data_len); if cap_accounts_data_len { - let pre_data_len = pre_account.data().len() as i64; - let post_data_len = account.data().len() as i64; - let data_len_delta = post_data_len.saturating_sub(pre_data_len); self.accounts_data_meter.consume(data_len_delta)?; + } else { + self.accounts_data_meter.consume_unchecked(data_len_delta); } return Ok(()); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 1def36220d439f..77ea18faaafe4b 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -4161,7 +4161,7 @@ impl Bank { } /// Update the accounts data len by adding `delta`. Since `delta` is signed, negative values - /// are allowed as the means to subtract from `accounts_data_len`. + /// are allowed as the means to subtract from `accounts_data_len`. The arithmetic saturates. fn update_accounts_data_len(&self, delta: i64) { /// Mixed integer ops currently not stable, so copying the impl. /// Copied from: https://github.com/a1phyr/rust/blob/47edde1086412b36e9efd6098b191ec15a2a760a/library/core/src/num/uint_macros.rs#L1039-L1048 @@ -4609,11 +4609,7 @@ impl Bank { .write() .unwrap() .extend(rent_debits.into_unordered_rewards_iter()); - if self - .feature_set - .is_active(&feature_set::cap_accounts_data_len::id()) - && total_collected.account_data_len_reclaimed > 0 - { + if total_collected.account_data_len_reclaimed > 0 { self.update_accounts_data_len(-(total_collected.account_data_len_reclaimed as i64)); }