From 6edd589138b082a92d7e9c4d24ee0a6df34ee1e0 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 20 Apr 2023 07:00:15 +0200 Subject: [PATCH] Gas and more for `CREATE(2)` (#995) * Gas * Codehash * Minor --- evm/src/cpu/kernel/asm/core/create.asm | 70 ++++++++++++++++++++-- evm/src/cpu/kernel/asm/memory/metadata.asm | 9 +++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/create.asm b/evm/src/cpu/kernel/asm/core/create.asm index 866e482c..573d1348 100644 --- a/evm/src/cpu/kernel/asm/core/create.asm +++ b/evm/src/cpu/kernel/asm/core/create.asm @@ -5,8 +5,13 @@ // Post stack: address global sys_create: %check_static + + %stack (kexit_info, value, code_offset, code_len) -> (code_len, code_offset, kexit_info, value, code_offset, code_len) + %checked_mem_expansion // stack: kexit_info, value, code_offset, code_len - // TODO: Charge gas. + %charge_gas_const(@GAS_CREATE) + // TODO: If using EIP-3860, we should limit and charge gas on `code_len`. + %stack (kexit_info, value, code_offset, code_len) -> (sys_create_got_address, value, code_offset, code_len, kexit_info) %address @@ -27,8 +32,15 @@ sys_create_got_address: // Post stack: address global sys_create2: %check_static + // stack: kexit_info, value, code_offset, code_len, salt - // TODO: Charge gas. + %stack (kexit_info, value, code_offset, code_len) -> (code_len, code_offset, kexit_info, value, code_offset, code_len) + %checked_mem_expansion + // stack: kexit_info, value, code_offset, code_len, salt + DUP4 %num_bytes_to_num_words + %mul_const(@GAS_KECCAK256WORD) %add_const(@GAS_CREATE) %charge_gas + // TODO: If using EIP-3860, we should limit and charge gas on `code_len`. + SWAP4 %stack (salt) -> (salt, create_common) // stack: salt, create_common, value, code_offset, code_len, kexit_info @@ -78,7 +90,10 @@ global create_common: GET_CONTEXT // stack: src_ctx, new_ctx, address, value, code_offset, code_len, kexit_info - // Copy the code from txdata to the new context's code segment. + %stack (src_ctx, new_ctx, address, value, code_offset, code_len) -> + (code_len, new_ctx, src_ctx, new_ctx, address, value, code_offset, code_len) + %set_new_ctx_code_size POP + // Copy the code from memory to the new context's code segment. %stack (src_ctx, new_ctx, address, value, code_offset, code_len) -> (new_ctx, @SEGMENT_CODE, 0, // DST src_ctx, @SEGMENT_MAIN_MEMORY, code_offset, // SRC @@ -113,7 +128,32 @@ after_constructor: // stack: success, leftover_gas, new_ctx, address, kexit_info SWAP2 // stack: new_ctx, leftover_gas, success, address, kexit_info - POP // TODO: Ignoring new_ctx for now, but we will need it to store code that was returned, if any. + POP + + // TODO: EIP-170: Contract code size limit. + // TODO: EIP-3541: Reject new contract code starting with the 0xEF byte + + // TODO: Skip blocks below if success is false. + // Charge gas for the code size. + SWAP3 + // stack: kexit_info, success, address, leftover_gas + %returndatasize // Size of the code. + %mul_const(@GAS_CODEDEPOSIT) %charge_gas + SWAP3 + + // Store the code hash of the new contract. + GET_CONTEXT + %returndatasize + %stack (size, ctx) -> (ctx, @SEGMENT_RETURNDATA, 0, size) // context, segment, offset, len + KECCAK_GENERAL + // stack: codehash, leftover_gas, success, address, kexit_info + DUP4 + // stack: address, codehash, leftover_gas, success, address, kexit_info + %set_codehash + + // Set the return data size to 0. + %mstore_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 0) + // stack: leftover_gas, success, address, kexit_info %shl_const(192) // stack: leftover_gas << 192, success, address, kexit_info @@ -123,6 +163,26 @@ after_constructor: // stack: address_if_success, leftover_gas << 192, kexit_info SWAP2 // stack: kexit_info, leftover_gas << 192, address_if_success - ADD + SUB // stack: kexit_info, address_if_success EXIT_KERNEL + +%macro set_codehash + %stack (addr, codehash) -> (addr, codehash, %%after) + %jump(set_codehash) +%%after: + // stack: (empty) +%endmacro + +// Pre stack: addr, codehash, redest +// Post stack: (empty) +// TODO: Should it be copy-on-write (with make_account_copy) instead of mutating the trie? +set_codehash: + // stack: addr, codehash, retdest + %mpt_read_state_trie + // stack: account_ptr, codehash, retdest + %add_const(3) + // stack: codehash_ptr, codehash, retdest + %mstore_trie_data + // stack: retdest + JUMP diff --git a/evm/src/cpu/kernel/asm/memory/metadata.asm b/evm/src/cpu/kernel/asm/memory/metadata.asm index c158718b..42a88957 100644 --- a/evm/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm/src/cpu/kernel/asm/memory/metadata.asm @@ -34,6 +34,15 @@ // stack: (empty) %endmacro +// Store the given context metadata field to memory. +%macro mstore_context_metadata(field, value) + PUSH $value + PUSH $field + // stack: offset, value + %mstore_current(@SEGMENT_CONTEXT_METADATA) + // stack: (empty) +%endmacro + %macro mstore_parent_context_metadata(field) // stack: value %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT)