Skip to content

Commit

Permalink
Optimizes conversion of bytes to words (#985)
Browse files Browse the repository at this point in the history
* ceil to bytes32

* overflow and nits
  • Loading branch information
lordshashank authored Sep 30, 2024
1 parent c645fee commit 7c289ed
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 30 deletions.
4 changes: 2 additions & 2 deletions crates/evm/src/create_helpers.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::stack::StackTrait;
use crate::state::StateTrait;
use utils::address::{compute_contract_address, compute_create2_contract_address};
use utils::constants;
use utils::helpers::ceil32;
use utils::helpers::bytes_32_words_size;
use utils::set::SetTrait;
use utils::traits::{
BoolIntoNumeric, EthAddressIntoU256, U256TryIntoResult, SpanU8TryIntoResultEthAddress
Expand Down Expand Up @@ -48,7 +48,7 @@ pub impl CreateHelpersImpl of CreateHelpers {
let charged_gas = match create_type {
CreateType::Create => gas::CREATE + memory_expansion.expansion_cost + init_code_gas,
CreateType::Create2 => {
let calldata_words = ceil32(size) / 32;
let calldata_words = bytes_32_words_size(size);
gas::CREATE
+ gas::KECCAK256WORD * calldata_words.into()
+ memory_expansion.expansion_cost
Expand Down
4 changes: 2 additions & 2 deletions crates/evm/src/gas.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ pub fn memory_expansion(
}
}?;

let new_size = helpers::ceil32(max_size);
let new_size = helpers::bytes_32_words_size(max_size) * 32;

if new_size <= current_size {
return Result::Ok(MemoryExpansion { new_size: current_size, expansion_cost: 0 });
Expand All @@ -218,7 +218,7 @@ pub fn memory_expansion(
/// * `init_code_gas` - The gas to be charged for the init code.
#[inline(always)]
pub fn init_code_cost(code_size: usize) -> u64 {
let code_size_in_words = helpers::ceil32(code_size) / 32;
let code_size_in_words = helpers::bytes_32_words_size(code_size);
code_size_in_words.into() * INITCODE_WORD_COST
}

Expand Down
11 changes: 5 additions & 6 deletions crates/evm/src/instructions/environmental_information.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::model::vm::{VM, VMTrait};
use crate::model::{AddressTrait};
use crate::stack::StackTrait;
use crate::state::StateTrait;
use utils::helpers::{ceil32, load_word};
use utils::helpers::{bytes_32_words_size, load_word};
use utils::set::SetTrait;
use utils::traits::{EthAddressIntoU256};

Expand Down Expand Up @@ -113,7 +113,7 @@ pub impl EnvironmentInformationImpl of EnvironmentInformationTrait {
let offset = self.stack.pop_saturating_usize()?;
let size = self.stack.pop_usize()?;

let words_size = (ceil32(size) / 32).into();
let words_size = bytes_32_words_size(size).into();
let copy_gas_cost = gas::COPY * words_size;
let memory_expansion = gas::memory_expansion(
self.memory.size(), [(dest_offset, size)].span()
Expand Down Expand Up @@ -143,7 +143,7 @@ pub impl EnvironmentInformationImpl of EnvironmentInformationTrait {
let offset = self.stack.pop_saturating_usize()?;
let size = self.stack.pop_usize()?;

let words_size = (ceil32(size) / 32).into();
let words_size = bytes_32_words_size(size).into();
let copy_gas_cost = gas::COPY * words_size;
let memory_expansion = gas::memory_expansion(
self.memory.size(), [(dest_offset, size)].span()
Expand Down Expand Up @@ -193,7 +193,7 @@ pub impl EnvironmentInformationImpl of EnvironmentInformationTrait {
let size = self.stack.pop_usize()?;

// GAS
let words_size = (ceil32(size) / 32).into();
let words_size = bytes_32_words_size(size).into();
let memory_expansion = gas::memory_expansion(
self.memory.size(), [(dest_offset, size)].span()
)?;
Expand Down Expand Up @@ -236,8 +236,7 @@ pub impl EnvironmentInformationImpl of EnvironmentInformationTrait {
}
ensure(!(last_returndata_index > return_data.len()), EVMError::ReturnDataOutOfBounds)?;

//TODO: handle overflow in ceil32 function.
let words_size = (ceil32(size.into()) / 32).into();
let words_size = bytes_32_words_size(size).into();
let copy_gas_cost = gas::COPY * words_size;

let memory_expansion = gas::memory_expansion(
Expand Down
4 changes: 2 additions & 2 deletions crates/evm/src/instructions/memory_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::memory::MemoryTrait;
use crate::model::vm::{VM, VMTrait};
use crate::stack::StackTrait;
use crate::state::StateTrait;
use utils::helpers::ceil32;
use utils::helpers::bytes_32_words_size;
use utils::set::SetTrait;

#[inline(always)]
Expand Down Expand Up @@ -282,7 +282,7 @@ pub impl MemoryOperation of MemoryOperationTrait {
let source_offset = self.stack.pop_usize()?;
let size = self.stack.pop_usize()?;

let words_size = (ceil32(size) / 32).into();
let words_size = bytes_32_words_size(size).into();
let copy_gas_cost = gas::COPY * words_size;
let memory_expansion = gas::memory_expansion(
self.memory.size(), [(max(dest_offset, source_offset), size)].span()
Expand Down
4 changes: 2 additions & 2 deletions crates/evm/src/instructions/sha3.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::gas;
use crate::memory::MemoryTrait;
use crate::model::vm::{VM, VMTrait};
use crate::stack::StackTrait;
use utils::helpers::ceil32;
use utils::helpers::bytes_32_words_size;
use utils::traits::array::ArrayExtTrait;
use utils::traits::integer::U256Trait;

Expand All @@ -26,7 +26,7 @@ pub impl Sha3Impl of Sha3Trait {
let offset: usize = self.stack.pop_usize()?;
let mut size: usize = self.stack.pop_usize()?;

let words_size = (ceil32(size) / 32).into();
let words_size = bytes_32_words_size(size).into();
let word_gas_cost = gas::KECCAK256WORD * words_size;
let memory_expansion = gas::memory_expansion(self.memory.size(), [(offset, size)].span())?;
self.memory.ensure_length(memory_expansion.new_size);
Expand Down
31 changes: 15 additions & 16 deletions crates/utils/src/helpers.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use core::array::ArrayTrait;
use core::array::SpanTrait;
use core::cmp::min;
use core::hash::{HashStateExTrait, HashStateTrait};
use core::num::traits::SaturatingAdd;

use core::panic_with_felt252;
use core::pedersen::PedersenTrait;
Expand Down Expand Up @@ -31,28 +32,20 @@ pub fn u128_split(input: u128) -> (u64, u64) {
(high.try_into().unwrap(), low.try_into().unwrap())
}


/// Converts a value to the next closest multiple of 32
/// Computes the number of 32-byte words required to represent `size` bytes
///
/// # Arguments
/// * `value` - The value to ceil to the next multiple of 32
/// * `size` - The size in bytes
///
/// # Returns
/// The same value if it's a perfect multiple of 32
/// else it returns the smallest multiple of 32
/// that is greater than `value`.
/// The number of 32-byte words required to represent `size` bytes
///
/// # Examples
/// ceil32(2) = 32
/// ceil32(34) = 64
pub fn ceil32(value: usize) -> usize {
let ceiling = 32_u32;
let (_q, r) = DivRem::div_rem(value, ceiling.try_into().unwrap());
if r == 0_u8.into() {
return value;
} else {
return (value + ceiling - r).into();
}
/// bytes_32_words_size(2) = 1
/// bytes_32_words_size(34) = 2
#[inline(always)]
pub fn bytes_32_words_size(size: usize) -> usize {
size.saturating_add(31) / 32
}

/// Computes 256 ** (16 - i) for 0 <= i <= 16.
Expand Down Expand Up @@ -357,4 +350,10 @@ mod tests {
assert_eq!(*dst4[counter], 0xff);
};
}

#[test]
fn test_bytes_32_words_size_edge_case() {
let max_usize = core::num::traits::Bounded::<usize>::MAX;
assert_eq!(helpers::bytes_32_words_size(max_usize), (max_usize / 32));
}
}

0 comments on commit 7c289ed

Please sign in to comment.