Skip to content

Commit

Permalink
fix(levm): ginitcodeword specification, fix gas (#1402)
Browse files Browse the repository at this point in the history
**Motivation**

<!-- Why does this pull request exist? What are its goals? -->

**Description**

<!-- A clear and concise general description of the changes this PR
introduces -->
- `number_of_words` is now calculated in a more performant way, without
iterating calldata.
- The initial_call_frame in Create is now initialized with empty
bytecode and the corresponding calldata send in the transaction. ->
After validations the calldata will be assigned to the bytecode and it
will be erased. This is mostly for using calldata for calculating some
gas costs.

<!-- Link to issues: Resolves #111, Resolves #222 -->

Closes #1362, #1363 

Running tests:
- ✓ Summary: 1547/4100 (37.73)
  • Loading branch information
JereSalo authored Dec 5, 2024
1 parent 3396ce8 commit 6777bfb
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 11 deletions.
21 changes: 10 additions & 11 deletions crates/vm/levm/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,13 @@ impl VM {
let created_contract = Account::new(value, calldata.clone(), 1, HashMap::new());
cache::insert_account(&mut cache, new_contract_address, created_contract);

let bytecode: Bytes = calldata.clone();

let initial_call_frame = CallFrame::new(
env.origin,
new_contract_address,
new_contract_address,
bytecode,
Bytes::new(), // Bytecode is assigned after passing validations.
value,
Bytes::new(), // Contract creation does not have calldata
calldata, // Calldata is removed after passing validations.
false,
env.gas_limit,
U256::zero(),
Expand Down Expand Up @@ -378,12 +376,7 @@ impl VM {
.checked_add(CREATE_BASE_COST)
.ok_or(OutOfGasError::ConsumedGasOverflow)?;

let number_of_words: u64 = initial_call_frame
.calldata
.chunks(WORD_SIZE)
.len()
.try_into()
.map_err(|_| InternalError::ConversionError)?;
let number_of_words = initial_call_frame.calldata.len().div_ceil(WORD_SIZE);

intrinsic_gas = intrinsic_gas
.checked_add(
Expand Down Expand Up @@ -493,7 +486,7 @@ impl VM {
// (4) INITCODE_SIZE_EXCEEDED
if self.is_create() {
// INITCODE_SIZE_EXCEEDED
if initial_call_frame.bytecode.len() > INIT_CODE_MAX_SIZE {
if initial_call_frame.calldata.len() > INIT_CODE_MAX_SIZE {
return Err(VMError::TxValidation(
TxValidationError::InitcodeSizeExceeded,
));
Expand Down Expand Up @@ -589,6 +582,12 @@ impl VM {
let cache_before_execution = self.cache.clone();
self.validate_transaction(&mut initial_call_frame)?;

if self.is_create() {
// Assign bytecode to context and empty calldata
initial_call_frame.bytecode = initial_call_frame.calldata.clone();
initial_call_frame.calldata = Bytes::new();
}

// Maybe can be done in validate_transaction
let sender = initial_call_frame.msg_sender;
let receiver_address = initial_call_frame.to;
Expand Down
2 changes: 2 additions & 0 deletions crates/vm/levm/tests/edge_case_tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Here add #![allow(clippy::<lint_name>)] if necessary, we don't want to lint the test code.

use std::str::FromStr;

use bytes::Bytes;
Expand Down

0 comments on commit 6777bfb

Please sign in to comment.