diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 402048d4..1da28e0b 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -145,6 +145,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/journal/storage_loaded.asm"), include_str!("asm/journal/code_change.asm"), include_str!("asm/journal/refund.asm"), + include_str!("asm/journal/account_created.asm"), include_str!("asm/journal/revert.asm"), include_str!("asm/transactions/common_decoding.asm"), include_str!("asm/transactions/router.asm"), diff --git a/evm/src/cpu/kernel/asm/core/call.asm b/evm/src/cpu/kernel/asm/core/call.asm index 6176674a..1af4c5e8 100644 --- a/evm/src/cpu/kernel/asm/core/call.asm +++ b/evm/src/cpu/kernel/asm/core/call.asm @@ -230,6 +230,8 @@ call_insufficient_balance: %stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) -> (callgas, kexit_info, 0) %shl_const(192) SWAP1 SUB + // stack: kexit_info', 0 + %mstore_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 0) EXIT_KERNEL // Set @CTX_METADATA_STATIC to 1. Note that there is no corresponding set_static_false routine diff --git a/evm/src/cpu/kernel/asm/core/create.asm b/evm/src/cpu/kernel/asm/core/create.asm index beeb759b..0dabef7d 100644 --- a/evm/src/cpu/kernel/asm/core/create.asm +++ b/evm/src/cpu/kernel/asm/core/create.asm @@ -70,11 +70,15 @@ global create_common: // stack: address, value, code_offset, code_len, kexit_info DUP1 %insert_accessed_addresses_no_return + // TODO: Check call stack depth. + // TODO: Check balance of caller first. // Increment the sender's nonce. %address %increment_nonce // stack: address, value, code_offset, code_len, kexit_info + %checkpoint + // Deduct value from the caller. DUP2 %address @@ -133,13 +137,15 @@ run_constructor: // (Old context) stack: new_ctx, address, kexit_info after_constructor: + // stack: success, leftover_gas, new_ctx, address, kexit_info + DUP1 ISZERO %jumpi(after_constructor_failed) + %pop_checkpoint + // stack: success, leftover_gas, new_ctx, address, kexit_info SWAP2 // stack: new_ctx, leftover_gas, success, address, kexit_info POP - - // TODO: Skip blocks below if success is false. // EIP-3541: Reject new contract code starting with the 0xEF byte PUSH 0 %mload_current(@SEGMENT_RETURNDATA) %eq_const(0xEF) %jumpi(fault_exception) @@ -168,6 +174,7 @@ after_constructor: // Set the return data size to 0. %mstore_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 0) +after_constructor_contd: // stack: leftover_gas, success, address, kexit_info %shl_const(192) // stack: leftover_gas << 192, success, address, kexit_info @@ -181,6 +188,11 @@ after_constructor: // stack: kexit_info, address_if_success EXIT_KERNEL +after_constructor_failed: + %revert_checkpoint + %stack (success, leftover_gas, new_ctx, address, kexit_info) -> (leftover_gas, success, address, kexit_info) + %jump(after_constructor_contd) + %macro set_codehash %stack (addr, codehash) -> (addr, codehash, %%after) %jump(set_codehash) diff --git a/evm/src/cpu/kernel/asm/core/create_contract_account.asm b/evm/src/cpu/kernel/asm/core/create_contract_account.asm index e7c346fb..339ea4a6 100644 --- a/evm/src/cpu/kernel/asm/core/create_contract_account.asm +++ b/evm/src/cpu/kernel/asm/core/create_contract_account.asm @@ -3,6 +3,7 @@ // Post stack: status %macro create_contract_account // stack: value, address + DUP2 %journal_add_account_created DUP2 %insert_touched_addresses DUP2 %mpt_read_state_trie // stack: existing_account_ptr, value, address diff --git a/evm/src/cpu/kernel/asm/core/terminate.asm b/evm/src/cpu/kernel/asm/core/terminate.asm index b90b14c5..a2a88835 100644 --- a/evm/src/cpu/kernel/asm/core/terminate.asm +++ b/evm/src/cpu/kernel/asm/core/terminate.asm @@ -139,7 +139,7 @@ global sys_revert: sys_revert_finish: %leftover_gas // stack: leftover_gas - // TODO: Revert state changes. + %revert_checkpoint PUSH 0 // success %jump(terminate_common) diff --git a/evm/src/cpu/kernel/asm/journal/account_created.asm b/evm/src/cpu/kernel/asm/journal/account_created.asm new file mode 100644 index 00000000..4748d5cb --- /dev/null +++ b/evm/src/cpu/kernel/asm/journal/account_created.asm @@ -0,0 +1,13 @@ +// struct AccountCreated { address } + +%macro journal_add_account_created + %journal_add_1(@JOURNAL_ENTRY_ACCOUNT_CREATED) +%endmacro + +global revert_account_created: + // stack: entry_type, ptr, retdest + POP + %journal_load_1 + // stack: address, retdest + %delete_account + JUMP diff --git a/evm/src/cpu/kernel/asm/journal/revert.asm b/evm/src/cpu/kernel/asm/journal/revert.asm index cc7bcc7c..1967239a 100644 --- a/evm/src/cpu/kernel/asm/journal/revert.asm +++ b/evm/src/cpu/kernel/asm/journal/revert.asm @@ -15,6 +15,7 @@ DUP1 %eq_const(@JOURNAL_ENTRY_STORAGE_LOADED) %jumpi(revert_storage_loaded) DUP1 %eq_const(@JOURNAL_ENTRY_CODE_CHANGE) %jumpi(revert_code_change) DUP1 %eq_const(@JOURNAL_ENTRY_REFUND) %jumpi(revert_refund) + DUP1 %eq_const(@JOURNAL_ENTRY_ACCOUNT_CREATED) %jumpi(revert_account_created) PANIC // This should never happen. %%after: // stack: journal_size-1 diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index 1f70ba91..cae5225d 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -126,7 +126,7 @@ sys_calldataload_after_mload_packing: PUSH @GAS_VERYLOW DUP5 // stack: size, Gverylow, kexit_info, dest_offset, offset, size - ISZERO %jumpi(%%wcopy_empty) + ISZERO %jumpi(wcopy_empty) // stack: Gverylow, kexit_info, dest_offset, offset, size DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD %charge_gas @@ -140,31 +140,31 @@ sys_calldataload_after_mload_packing: // stack: total_size, kexit_info, dest_offset, offset, size DUP4 // stack: offset, total_size, kexit_info, dest_offset, offset, size - GT %jumpi(%%wcopy_large_offset) + GT %jumpi(wcopy_large_offset) GET_CONTEXT %stack (context, kexit_info, dest_offset, offset, size) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, $segment, offset, size, %%after, kexit_info) + (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, $segment, offset, size, wcopy_after, kexit_info) %jump(memcpy) +%endmacro -%%after: - // stack: kexit_info - EXIT_KERNEL - -%%wcopy_empty: +wcopy_empty: // stack: Gverylow, kexit_info, dest_offset, offset, size %charge_gas %stack (kexit_info, dest_offset, offset, size) -> (kexit_info) EXIT_KERNEL -%%wcopy_large_offset: +wcopy_large_offset: // offset is larger than the size of the {CALLDATA,CODE,RETURNDATA}. So we just have to write zeros. // stack: kexit_info, dest_offset, offset, size GET_CONTEXT %stack (context, kexit_info, dest_offset, offset, size) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, 0, size, %%after, kexit_info) + (context, @SEGMENT_MAIN_MEMORY, dest_offset, 0, size, wcopy_after, kexit_info) %jump(memset) -%endmacro + +wcopy_after: + // stack: kexit_info + EXIT_KERNEL global sys_calldatacopy: %wcopy(@SEGMENT_CALLDATA, @CTX_METADATA_CALLDATA_SIZE) @@ -172,5 +172,32 @@ global sys_calldatacopy: global sys_codecopy: %wcopy(@SEGMENT_CODE, @CTX_METADATA_CODE_SIZE) +// Same as %wcopy but with overflow checks. global sys_returndatacopy: - %wcopy(@SEGMENT_RETURNDATA, @CTX_METADATA_RETURNDATA_SIZE) + // stack: kexit_info, dest_offset, offset, size + PUSH @GAS_VERYLOW + DUP5 + // stack: size, Gverylow, kexit_info, dest_offset, offset, size + ISZERO %jumpi(wcopy_empty) + // stack: Gverylow, kexit_info, dest_offset, offset, size + DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD %charge_gas + + %stack (kexit_info, dest_offset, offset, size) -> (dest_offset, size, kexit_info, dest_offset, offset, size) + %add_or_fault + // stack: expanded_num_bytes, kexit_info, dest_offset, offset, size, kexit_info + DUP1 %ensure_reasonable_offset + %update_mem_bytes + // stack: kexit_info, dest_offset, offset, size, kexit_info + DUP4 DUP4 %add_or_fault // Overflow check + %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) LT %jumpi(fault_exception) // Data len check + + %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) + // stack: total_size, kexit_info, dest_offset, offset, size + DUP4 + // stack: offset, total_size, kexit_info, dest_offset, offset, size + GT %jumpi(wcopy_large_offset) + + GET_CONTEXT + %stack (context, kexit_info, dest_offset, offset, size) -> + (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, @SEGMENT_RETURNDATA, offset, size, wcopy_after, kexit_info) + %jump(memcpy) diff --git a/evm/src/cpu/kernel/constants/journal_entry.rs b/evm/src/cpu/kernel/constants/journal_entry.rs index 3b6190ae..be5db120 100644 --- a/evm/src/cpu/kernel/constants/journal_entry.rs +++ b/evm/src/cpu/kernel/constants/journal_entry.rs @@ -10,10 +10,11 @@ pub(crate) enum JournalEntry { StorageLoaded = 6, CodeChange = 7, Refund = 8, + AccountCreated = 9, } impl JournalEntry { - pub(crate) const COUNT: usize = 9; + pub(crate) const COUNT: usize = 10; pub(crate) fn all() -> [Self; Self::COUNT] { [ @@ -26,6 +27,7 @@ impl JournalEntry { Self::StorageLoaded, Self::CodeChange, Self::Refund, + Self::AccountCreated, ] } @@ -41,6 +43,7 @@ impl JournalEntry { Self::StorageLoaded => "JOURNAL_ENTRY_STORAGE_LOADED", Self::CodeChange => "JOURNAL_ENTRY_CODE_CHANGE", Self::Refund => "JOURNAL_ENTRY_REFUND", + Self::AccountCreated => "JOURNAL_ENTRY_ACCOUNT_CREATED", } } }