diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index ee198198..4dddc6df 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -80,110 +80,6 @@ global extcodesize: // stack: extcodesize(address), retdest SWAP1 JUMP -%macro extcodecopy - // stack: address, dest_offset, offset, size - %stack (address, dest_offset, offset, size) -> (address, dest_offset, offset, size, %%after) - %jump(extcodecopy) -%%after: -%endmacro - -// Pre stack: kexit_info, address, dest_offset, offset, size -// Post stack: (empty) -global sys_extcodecopy: - %stack (kexit_info, address, dest_offset, offset, size) - -> (address, dest_offset, offset, size, kexit_info) - %u256_to_addr DUP1 %insert_accessed_addresses - // stack: cold_access, address, dest_offset, offset, size, kexit_info - PUSH @GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS - MUL - PUSH @GAS_WARMACCESS - ADD - // stack: Gaccess, address, dest_offset, offset, size, kexit_info - - DUP5 - // stack: size, Gaccess, address, dest_offset, offset, size, kexit_info - ISZERO %jumpi(sys_extcodecopy_empty) - - // stack: Gaccess, address, dest_offset, offset, size, kexit_info - DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD - %stack (gas, address, dest_offset, offset, size, kexit_info) -> (gas, kexit_info, address, dest_offset, offset, size) - %charge_gas - - %stack (kexit_info, address, dest_offset, offset, size) -> (dest_offset, size, kexit_info, address, dest_offset, offset, size) - %add_or_fault - // stack: expanded_num_bytes, kexit_info, address, dest_offset, offset, size - DUP1 %ensure_reasonable_offset - %update_mem_bytes - - %stack (kexit_info, address, dest_offset, offset, size) -> (address, dest_offset, offset, size, kexit_info) - %extcodecopy - // stack: kexit_info - EXIT_KERNEL - -sys_extcodecopy_empty: - %stack (Gaccess, address, dest_offset, offset, size, kexit_info) -> (Gaccess, kexit_info) - %charge_gas - EXIT_KERNEL - - -// Pre stack: address, dest_offset, offset, size, retdest -// Post stack: (empty) -global extcodecopy: - // stack: address, dest_offset, offset, size, retdest - %stack (address, dest_offset, offset, size, retdest) - -> (address, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, extcodecopy_contd, size, offset, dest_offset, retdest) - %jump(load_code) - -extcodecopy_contd: - // stack: code_size, size, offset, dest_offset, retdest - DUP1 DUP4 - // stack: offset, code_size, code_size, size, offset, dest_offset, retdest - GT %jumpi(extcodecopy_large_offset) - - // stack: code_size, size, offset, dest_offset, retdest - DUP3 DUP3 ADD - // stack: offset + size, code_size, size, offset, dest_offset, retdest - DUP2 GT %jumpi(extcodecopy_within_bounds) - - // stack: code_size, size, offset, dest_offset, retdest - DUP3 DUP3 ADD - // stack: offset + size, code_size, size, offset, dest_offset, retdest - SUB - // stack: extra_size = offset + size - code_size, size, offset, dest_offset, retdest - DUP1 DUP3 SUB - // stack: copy_size = size - extra_size, extra_size, size, offset, dest_offset, retdest - - // Compute the new dest_offset after actual copies, at which we will start padding with zeroes. - DUP1 DUP6 ADD - // stack: new_dest_offset, copy_size, extra_size, size, offset, dest_offset, retdest - - GET_CONTEXT - %stack (context, new_dest_offset, copy_size, extra_size, size, offset, dest_offset, retdest) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, offset, copy_size, extcodecopy_end, new_dest_offset, extra_size, retdest) - %jump(memcpy_bytes) - -extcodecopy_within_bounds: - // stack: code_size, size, offset, dest_offset, retdest - GET_CONTEXT - %stack (context, code_size, size, offset, dest_offset, retdest) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, offset, size, retdest) - %jump(memcpy_bytes) - -// Same as extcodecopy_large_offset, but without `offset` in the stack. -extcodecopy_end: - // stack: dest_offset, size, retdest - GET_CONTEXT - %stack (context, dest_offset, size, retdest) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, size, retdest) - %jump(memset) - -extcodecopy_large_offset: - // offset is larger than the code size. So we just have to write zeros. - // stack: code_size, size, offset, dest_offset, retdest - GET_CONTEXT - %stack (context, code_size, size, offset, dest_offset, retdest) -> (context, @SEGMENT_MAIN_MEMORY, dest_offset, size, retdest) - %jump(memset) - // Loads the code at `address` into memory, at the given context and segment, starting at offset 0. // Checks that the hash of the loaded code corresponds to the `codehash` in the state trie. // Pre stack: address, ctx, segment, retdest diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index ad041c44..dd4787fe 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -106,6 +106,10 @@ calldataload_large_offset: DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD %charge_gas %endmacro + +codecopy_within_bounds: + // stack: total_size, segment, kexit_info, dest_offset, offset, size + POP wcopy_within_bounds: // stack: segment, kexit_info, dest_offset, offset, size GET_CONTEXT @@ -119,6 +123,10 @@ wcopy_empty: %stack (kexit_info, dest_offset, offset, size) -> (kexit_info) EXIT_KERNEL + +codecopy_large_offset: + // stack: total_size, kexit_info, dest_offset, offset, size + POP 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 @@ -131,16 +139,19 @@ wcopy_after: // stack: kexit_info EXIT_KERNEL +// Pre stack: kexit_info, dest_offset, offset, size +// Post stack: (empty) global sys_calldatacopy: %wcopy(@SEGMENT_CALLDATA, @CTX_METADATA_CALLDATA_SIZE) -global sys_codecopy: - %codecopy(@SEGMENT_CODE, @CTX_METADATA_CODE_SIZE) - +// Pre stack: kexit_info, dest_offset, offset, size +// Post stack: (empty) global sys_returndatacopy: %wcopy(@SEGMENT_RETURNDATA, @CTX_METADATA_RETURNDATA_SIZE) -%macro codecopy(segment, context_metadata_size) +// Pre stack: kexit_info, dest_offset, offset, size +// Post stack: (empty) +global sys_codecopy: // stack: kexit_info, dest_offset, offset, size %wcopy_charge_gas @@ -150,20 +161,67 @@ global sys_returndatacopy: DUP1 %ensure_reasonable_offset %update_mem_bytes - %mload_context_metadata($context_metadata_size) + %mload_context_metadata(@CTX_METADATA_CODE_SIZE) + // stack: code_size, kexit_info, dest_offset, offset, size, + %codecopy_after_checks(@SEGMENT_CODE) + + +// Pre stack: kexit_info, address, dest_offset, offset, size +// Post stack: (empty) +global sys_extcodecopy: + %stack (kexit_info, address, dest_offset, offset, size) + -> (address, dest_offset, offset, size, kexit_info) + %u256_to_addr DUP1 %insert_accessed_addresses + // stack: cold_access, address, dest_offset, offset, size, kexit_info + PUSH @GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS + MUL + PUSH @GAS_WARMACCESS + ADD + // stack: Gaccess, address, dest_offset, offset, size, kexit_info + + DUP5 + // stack: size, Gaccess, address, dest_offset, offset, size, kexit_info + ISZERO %jumpi(sys_extcodecopy_empty) + + // stack: Gaccess, address, dest_offset, offset, size, kexit_info + DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD + %stack (gas, address, dest_offset, offset, size, kexit_info) -> (gas, kexit_info, address, dest_offset, offset, size) + %charge_gas + + %stack (kexit_info, address, dest_offset, offset, size) -> (dest_offset, size, kexit_info, address, dest_offset, offset, size) + %add_or_fault + // stack: expanded_num_bytes, kexit_info, address, dest_offset, offset, size + DUP1 %ensure_reasonable_offset + %update_mem_bytes + + %stack (kexit_info, address, dest_offset, offset, size) -> + (address, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, extcodecopy_contd, kexit_info, dest_offset, offset, size) + %jump(load_code) + +sys_extcodecopy_empty: + %stack (Gaccess, address, dest_offset, offset, size, kexit_info) -> (Gaccess, kexit_info) + %charge_gas + EXIT_KERNEL + +extcodecopy_contd: + // stack: code_size, kexit_info, dest_offset, offset, size + %codecopy_after_checks(@SEGMENT_KERNEL_ACCOUNT_CODE) + + +// The internal logic is similar to wcopy, but handles range overflow differently. +// It is used for both CODECOPY and EXTCODECOPY. +%macro codecopy_after_checks(segment) // 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) + DUP1 DUP5 + // stack: offset, total_size, total_size, kexit_info, dest_offset, offset, size + GT %jumpi(codecopy_large_offset) - PUSH $segment - %mload_context_metadata($context_metadata_size) + PUSH $segment SWAP1 // stack: total_size, segment, kexit_info, dest_offset, offset, size - DUP6 DUP6 ADD - // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size - LT %jumpi(wcopy_within_bounds) + DUP1 DUP7 DUP7 ADD + // stack: offset + size, total_size, total_size, segment, kexit_info, dest_offset, offset, size + LT %jumpi(codecopy_within_bounds) - %mload_context_metadata($context_metadata_size) // stack: total_size, segment, kexit_info, dest_offset, offset, size DUP6 DUP6 ADD // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size