diff --git a/evm/src/cpu/kernel/asm/core/call.asm b/evm/src/cpu/kernel/asm/core/call.asm index 2777b8a8..e181246a 100644 --- a/evm/src/cpu/kernel/asm/core/call.asm +++ b/evm/src/cpu/kernel/asm/core/call.asm @@ -3,15 +3,22 @@ // Creates a new sub context and executes the code of the given account. global sys_call: // stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size - // TODO: Charge gas. SWAP2 // stack: address, gas, kexit_info, value, args_offset, args_size, ret_offset, ret_size %u256_to_addr // Truncate to 160 bits - DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation. - SWAP2 - // stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size + DUP1 %insert_accessed_addresses + + %call_charge_gas + + %stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) -> + (args_size, args_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) + %checked_mem_expansion + %stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) -> + (ret_size, ret_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) + %checked_mem_expansion + %create_context - // stack: new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size + // stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size // TODO: Consider call depth // Each line in the block below does not change the stack. @@ -20,15 +27,15 @@ global sys_call: DUP5 %set_new_ctx_value DUP5 DUP5 %address %transfer_eth %jumpi(panic) // TODO: Fix this panic. %set_new_ctx_parent_pc(after_call_instruction) - DUP3 %set_new_ctx_gas_limit // TODO: This is not correct in most cases. Use C_callgas as in the YP. + DUP3 %set_new_ctx_gas_limit DUP4 %set_new_ctx_code - %stack (new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size) -> - (new_ctx, args_offset, args_size, new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size) + %stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) -> + (new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) %copy_mem_to_calldata - // stack: new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size - %stack (new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size) + // stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size + %stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) -> (new_ctx, kexit_info, ret_offset, ret_size) %enter_new_ctx @@ -117,7 +124,7 @@ global after_call_instruction: SWAP3 // stack: kexit_info, leftover_gas, new_ctx, success, ret_offset, ret_size // Add the leftover gas into the appropriate bits of kexit_info. - SWAP1 %shl_const(192) ADD + SWAP1 %shl_const(192) SWAP1 SUB // stack: kexit_info, new_ctx, success, ret_offset, ret_size // The callee's terminal instruction will have populated RETURNDATA. @@ -250,3 +257,78 @@ global after_call_instruction: %jump(memcpy) %%after: %endmacro + +// Charge gas for *call opcodes and return the sub-context gas limit. +// Doesn't include memory expansion costs. +%macro call_charge_gas + // Compute C_aaccess + // stack: cold_access, address, gas, kexit_info, value, args_offset, args_size, ret_offset, ret_size + %mul_const(@GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS) + %add_const(@GAS_WARMACCESS) + + // Compute C_xfer + // stack: Caaccess, address, gas, kexit_info, value + DUP5 ISZERO PUSH 1 SUB + // stack: value≠0, Caaccess, address, gas, kexit_info, value + DUP1 + %mul_const(@GAS_CALLVALUE) + + // Compute C_new + // stack: Cxfer, value≠0, Caaccess, address, gas, kexit_info, value + SWAP1 + // stack: value≠0, Cxfer, Caaccess, address, gas, kexit_info, value + DUP4 %is_dead MUL + // stack: is_dead(address) and value≠0, Cxfer, Caaccess, address, gas, kexit_info, value + %mul_const(@GAS_NEWACCOUNT) + // stack: Cnew, Cxfer, Caaccess, address, gas, kexit_info, value + + // Compute C_extra + ADD ADD + + // Compute C_gascap + // stack: Cextra, address, gas, kexit_info, value + DUP4 %leftover_gas + // stack: leftover_gas, Cextra, address, gas, kexit_info, value + DUP2 DUP2 LT + // stack: leftover_gas=Cextra, (leftover_gas=Cextra, (leftover_gas=Cextra, (leftover_gas (Cextra, Cgascap, Cgascap) + ADD + %stack (C_call, Cgascap, address, gas, kexit_info, value) -> + (C_call, kexit_info, Cgascap, address, gas, value) + %charge_gas + + // Compute C_callgas + %stack (kexit_info, Cgascap, address, gas, value) -> + (Cgascap, address, gas, kexit_info, value) + DUP5 ISZERO PUSH 1 SUB + // stack: value!=0, Cgascap, address, gas, kexit_info, value + %mul_const(@GAS_CALLSTIPEND) ADD + %stack (C_callgas, address, gas, kexit_info, value) -> + (kexit_info, C_callgas, address, value) +%endmacro + +// Checked memory expansion. +%macro checked_mem_expansion + // stack: size, offset, kexit_info + DUP1 ISZERO %jumpi(%%zero) + ADD // TODO: check for overflow + // stack: expanded_num_bytes, kexit_info + DUP1 %ensure_reasonable_offset + %update_mem_bytes + %jump(%%after) +%%zero: + %pop2 +%%after: +%endmacro diff --git a/evm/src/cpu/kernel/asm/core/util.asm b/evm/src/cpu/kernel/asm/core/util.asm index de3dfb70..a8e41a7b 100644 --- a/evm/src/cpu/kernel/asm/core/util.asm +++ b/evm/src/cpu/kernel/asm/core/util.asm @@ -66,4 +66,4 @@ DUP1 %is_non_existent SWAP1 %is_empty ADD // OR -%endmacro \ No newline at end of file +%endmacro