From 0f7e1c0b612ec7992a3133d461001b172b766505 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 7 Jun 2023 18:54:06 +0200 Subject: [PATCH] Call stack depth (#1081) --- evm/src/cpu/kernel/asm/core/call.asm | 32 ++++++++++++++++--- evm/src/cpu/kernel/asm/core/terminate.asm | 1 + evm/src/cpu/kernel/asm/memory/metadata.asm | 16 ++++++++++ .../cpu/kernel/constants/global_metadata.rs | 5 ++- evm/src/cpu/kernel/constants/mod.rs | 2 ++ 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/call.asm b/evm/src/cpu/kernel/asm/core/call.asm index 9c60f66b..41662c5f 100644 --- a/evm/src/cpu/kernel/asm/core/call.asm +++ b/evm/src/cpu/kernel/asm/core/call.asm @@ -22,14 +22,15 @@ global sys_call: // 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 - %checkpoint // Checkpoint DUP2 %insert_touched_addresses %call_charge_gas(1, 1) + %check_depth + + %checkpoint // Checkpoint %create_context // stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size - // TODO: Consider call depth %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) @@ -74,9 +75,11 @@ global sys_callcode: // 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 - %checkpoint // Checkpoint %call_charge_gas(1, 0) + %check_depth + + %checkpoint // Checkpoint // stack: kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size %create_context @@ -127,12 +130,14 @@ global sys_staticcall: // stack: address, gas, kexit_info, args_offset, args_size, ret_offset, ret_size %u256_to_addr // Truncate to 160 bits DUP1 %insert_accessed_addresses - %checkpoint // Checkpoint DUP2 %insert_touched_addresses // Add a value of 0 to the stack. Slightly inefficient but that way we can reuse %call_charge_gas. %stack (cold_access, address, gas, kexit_info) -> (cold_access, address, gas, kexit_info, 0) %call_charge_gas(0, 1) + %check_depth + + %checkpoint // Checkpoint // stack: kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size %create_context @@ -180,11 +185,13 @@ global sys_delegatecall: // stack: address, gas, kexit_info, args_offset, args_size, ret_offset, ret_size %u256_to_addr // Truncate to 160 bits DUP1 %insert_accessed_addresses - %checkpoint // Checkpoint // Add a value of 0 to the stack. Slightly inefficient but that way we can reuse %call_charge_gas. %stack (cold_access, address, gas, kexit_info) -> (cold_access, address, gas, kexit_info, 0) %call_charge_gas(0, 0) + %check_depth + + %checkpoint // Checkpoint // stack: kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size %create_context @@ -244,6 +251,20 @@ call_insufficient_balance: %mstore_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 0) EXIT_KERNEL +%macro check_depth + %call_depth + %gt_const(@CALL_STACK_LIMIT) + %jumpi(call_too_deep) +%endmacro + +call_too_deep: + %stack (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 // because it will already be 0 by default. %macro set_static_true @@ -342,6 +363,7 @@ call_insufficient_balance: DUP1 // new_ctx SET_CONTEXT %checkpoint // Checkpoint + %increment_call_depth // Perform jumpdest analyis PUSH %%after %mload_context_metadata(@CTX_METADATA_CODE_SIZE) diff --git a/evm/src/cpu/kernel/asm/core/terminate.asm b/evm/src/cpu/kernel/asm/core/terminate.asm index ae92e2af..d11561ba 100644 --- a/evm/src/cpu/kernel/asm/core/terminate.asm +++ b/evm/src/cpu/kernel/asm/core/terminate.asm @@ -200,6 +200,7 @@ global terminate_common: // Go back to the parent context. %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) SET_CONTEXT + %decrement_call_depth // stack: (empty) // Load the fields that we stored in SEGMENT_KERNEL_GENERAL. diff --git a/evm/src/cpu/kernel/asm/memory/metadata.asm b/evm/src/cpu/kernel/asm/memory/metadata.asm index 9fb959f4..8d8eadf3 100644 --- a/evm/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm/src/cpu/kernel/asm/memory/metadata.asm @@ -325,3 +325,19 @@ global sys_basefee: %jumpi(fault_exception) // stack: sum %endmacro + +%macro call_depth + %mload_global_metadata(@GLOBAL_METADATA_CALL_STACK_DEPTH) +%endmacro + +%macro increment_call_depth + %mload_global_metadata(@GLOBAL_METADATA_CALL_STACK_DEPTH) + %increment + %mstore_global_metadata(@GLOBAL_METADATA_CALL_STACK_DEPTH) +%endmacro + +%macro decrement_call_depth + %mload_global_metadata(@GLOBAL_METADATA_CALL_STACK_DEPTH) + %decrement + %mstore_global_metadata(@GLOBAL_METADATA_CALL_STACK_DEPTH) +%endmacro diff --git a/evm/src/cpu/kernel/constants/global_metadata.rs b/evm/src/cpu/kernel/constants/global_metadata.rs index 99471fd4..3b6b80a4 100644 --- a/evm/src/cpu/kernel/constants/global_metadata.rs +++ b/evm/src/cpu/kernel/constants/global_metadata.rs @@ -68,10 +68,11 @@ pub(crate) enum GlobalMetadata { // Boolean flag indicating if the txn is a contract creation txn. ContractCreation = 33, IsPrecompileFromEoa = 34, + CallStackDepth = 35, } impl GlobalMetadata { - pub(crate) const COUNT: usize = 34; + pub(crate) const COUNT: usize = 35; pub(crate) fn all() -> [Self; Self::COUNT] { [ @@ -109,6 +110,7 @@ impl GlobalMetadata { Self::AccessListRlpLen, Self::ContractCreation, Self::IsPrecompileFromEoa, + Self::CallStackDepth, ] } @@ -149,6 +151,7 @@ impl GlobalMetadata { Self::AccessListRlpLen => "GLOBAL_METADATA_ACCESS_LIST_RLP_LEN", Self::ContractCreation => "GLOBAL_METADATA_CONTRACT_CREATION", Self::IsPrecompileFromEoa => "GLOBAL_METADATA_IS_PRECOMPILE_FROM_EOA", + Self::CallStackDepth => "GLOBAL_METADATA_CALL_STACK_DEPTH", } } } diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index ab702798..33699a79 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -55,6 +55,7 @@ pub fn evm_constants() -> HashMap { } c.insert(MAX_NONCE.0.into(), U256::from(MAX_NONCE.1)); + c.insert(CALL_STACK_LIMIT.0.into(), U256::from(CALL_STACK_LIMIT.1)); for segment in Segment::all() { c.insert(segment.var_name().into(), (segment as u32).into()); @@ -264,3 +265,4 @@ const CODE_SIZE_LIMIT: [(&str, u64); 3] = [ ]; const MAX_NONCE: (&str, u64) = ("MAX_NONCE", 0xffffffffffffffff); +const CALL_STACK_LIMIT: (&str, u64) = ("CALL_STACK_LIMIT", 1024);