From e6a7b8c5cbca9f365704efffdad784dbb4e651b8 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 24 May 2023 17:49:54 +0200 Subject: [PATCH] Add contract creation flag (#1056) * Add contract creation flag * Minor * Fix intrinsic gas test --- evm/src/cpu/kernel/asm/core/process_txn.asm | 2 +- evm/src/cpu/kernel/asm/core/util.asm | 6 +---- evm/src/cpu/kernel/asm/rlp/decode.asm | 2 +- .../asm/transactions/common_decoding.asm | 22 +++++++++++++++++-- .../cpu/kernel/asm/transactions/type_0.asm | 10 ++++----- .../cpu/kernel/asm/transactions/type_1.asm | 10 ++++----- .../cpu/kernel/asm/transactions/type_2.asm | 10 ++++----- .../cpu/kernel/constants/global_metadata.rs | 6 ++++- .../cpu/kernel/tests/core/intrinsic_gas.rs | 3 +++ 9 files changed, 46 insertions(+), 25 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/process_txn.asm b/evm/src/cpu/kernel/asm/core/process_txn.asm index 2eea69dd..61c66134 100644 --- a/evm/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm/src/cpu/kernel/asm/core/process_txn.asm @@ -407,5 +407,5 @@ contract_creation_fault_4: JUMP -invalid_txn: +global invalid_txn: %jump(txn_loop) diff --git a/evm/src/cpu/kernel/asm/core/util.asm b/evm/src/cpu/kernel/asm/core/util.asm index d64c6059..417a2d24 100644 --- a/evm/src/cpu/kernel/asm/core/util.asm +++ b/evm/src/cpu/kernel/asm/core/util.asm @@ -21,11 +21,7 @@ // Returns whether the current transaction is a contract creation transaction. %macro is_contract_creation // stack: (empty) - %mload_txn_field(@TXN_FIELD_TO) - // stack: to - ISZERO - // If there is no "to" field, then this is a contract creation. - // stack: to == 0 + %mload_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) %endmacro %macro is_precompile diff --git a/evm/src/cpu/kernel/asm/rlp/decode.asm b/evm/src/cpu/kernel/asm/rlp/decode.asm index 9842bfbd..327edcf1 100644 --- a/evm/src/cpu/kernel/asm/rlp/decode.asm +++ b/evm/src/cpu/kernel/asm/rlp/decode.asm @@ -130,7 +130,7 @@ decode_rlp_list_len_big: // fit in a single (256-bit) word on the stack. // Pre stack: pos, len, retdest // Post stack: pos', int -decode_int_given_len: +global decode_int_given_len: %stack (pos, len, retdest) -> (pos, len, pos, retdest) ADD // stack: end_pos, pos, retdest diff --git a/evm/src/cpu/kernel/asm/transactions/common_decoding.asm b/evm/src/cpu/kernel/asm/transactions/common_decoding.asm index 07d19f47..9b12d9c9 100644 --- a/evm/src/cpu/kernel/asm/transactions/common_decoding.asm +++ b/evm/src/cpu/kernel/asm/transactions/common_decoding.asm @@ -61,12 +61,30 @@ %endmacro // Decode the "to" field and store it. +// This field is either 160-bit or empty in the case of a contract creation txn. %macro decode_and_store_to // stack: pos - %decode_rlp_scalar - %stack (pos, to) -> (to, pos) + %decode_rlp_string_len + // stack: pos, len + SWAP1 + // stack: len, pos + DUP1 ISZERO %jumpi(%%contract_creation) + // stack: len, pos + DUP1 %eq_const(20) ISZERO %jumpi(invalid_txn) // Address is 160-bit + %stack (len, pos) -> (pos, len, %%with_scalar) + %jump(decode_int_given_len) +%%with_scalar: + // stack: pos, int + SWAP1 %mstore_txn_field(@TXN_FIELD_TO) // stack: pos + %jump(%%end) +%%contract_creation: + // stack: len, pos + POP + PUSH 1 %mstore_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) + // stack: pos +%%end: %endmacro // Decode the "value" field and store it. diff --git a/evm/src/cpu/kernel/asm/transactions/type_0.asm b/evm/src/cpu/kernel/asm/transactions/type_0.asm index 65836086..edd01e51 100644 --- a/evm/src/cpu/kernel/asm/transactions/type_0.asm +++ b/evm/src/cpu/kernel/asm/transactions/type_0.asm @@ -102,13 +102,13 @@ type_0_compute_signed_data: // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_TO) - DUP1 %jumpi(nonzero_to) - // stack: to, rlp_pos, rlp_start, retdest - SWAP1 %encode_rlp_scalar - %jump(after_to) -nonzero_to: + %mload_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) %jumpi(zero_to) // stack: to, rlp_pos, rlp_start, retdest SWAP1 %encode_rlp_160 + %jump(after_to) +zero_to: + // stack: to, rlp_pos, rlp_start, retdest + SWAP1 %encode_rlp_scalar // stack: rlp_pos, rlp_start, retdest after_to: diff --git a/evm/src/cpu/kernel/asm/transactions/type_1.asm b/evm/src/cpu/kernel/asm/transactions/type_1.asm index 9d1b4a6d..f8396e50 100644 --- a/evm/src/cpu/kernel/asm/transactions/type_1.asm +++ b/evm/src/cpu/kernel/asm/transactions/type_1.asm @@ -57,13 +57,13 @@ type_1_compute_signed_data: // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_TO) - DUP1 %jumpi(nonzero_to) - // stack: to, rlp_pos, rlp_start, retdest - SWAP1 %encode_rlp_scalar - %jump(after_to) -nonzero_to: + %mload_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) %jumpi(zero_to) // stack: to, rlp_pos, rlp_start, retdest SWAP1 %encode_rlp_160 + %jump(after_to) +zero_to: + // stack: to, rlp_pos, rlp_start, retdest + SWAP1 %encode_rlp_scalar // stack: rlp_pos, rlp_start, retdest after_to: diff --git a/evm/src/cpu/kernel/asm/transactions/type_2.asm b/evm/src/cpu/kernel/asm/transactions/type_2.asm index 464814eb..38f1980f 100644 --- a/evm/src/cpu/kernel/asm/transactions/type_2.asm +++ b/evm/src/cpu/kernel/asm/transactions/type_2.asm @@ -64,13 +64,13 @@ type_2_compute_signed_data: // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_TO) - DUP1 %jumpi(nonzero_to) - // stack: to, rlp_pos, rlp_start, retdest - SWAP1 %encode_rlp_scalar - %jump(after_to) -nonzero_to: + %mload_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) %jumpi(zero_to) // stack: to, rlp_pos, rlp_start, retdest SWAP1 %encode_rlp_160 + %jump(after_to) +zero_to: + // stack: to, rlp_pos, rlp_start, retdest + SWAP1 %encode_rlp_scalar // stack: rlp_pos, rlp_start, retdest after_to: diff --git a/evm/src/cpu/kernel/constants/global_metadata.rs b/evm/src/cpu/kernel/constants/global_metadata.rs index 2846b664..5cf8e138 100644 --- a/evm/src/cpu/kernel/constants/global_metadata.rs +++ b/evm/src/cpu/kernel/constants/global_metadata.rs @@ -65,10 +65,12 @@ pub(crate) enum GlobalMetadata { AccessListRlpStart = 31, // Length of the access list in the RLP for type-1 txns. AccessListRlpLen = 32, + // Boolean flag indicating if the txn is a contract creation txn. + ContractCreation = 33, } impl GlobalMetadata { - pub(crate) const COUNT: usize = 32; + pub(crate) const COUNT: usize = 33; pub(crate) fn all() -> [Self; Self::COUNT] { [ @@ -104,6 +106,7 @@ impl GlobalMetadata { Self::AccessListDataCost, Self::AccessListRlpStart, Self::AccessListRlpLen, + Self::ContractCreation, ] } @@ -142,6 +145,7 @@ impl GlobalMetadata { Self::AccessListDataCost => "GLOBAL_METADATA_ACCESS_LIST_DATA_COST", Self::AccessListRlpStart => "GLOBAL_METADATA_ACCESS_LIST_RLP_START", Self::AccessListRlpLen => "GLOBAL_METADATA_ACCESS_LIST_RLP_LEN", + Self::ContractCreation => "GLOBAL_METADATA_CONTRACT_CREATION", } } } diff --git a/evm/src/cpu/kernel/tests/core/intrinsic_gas.rs b/evm/src/cpu/kernel/tests/core/intrinsic_gas.rs index d84002ae..d8badef9 100644 --- a/evm/src/cpu/kernel/tests/core/intrinsic_gas.rs +++ b/evm/src/cpu/kernel/tests/core/intrinsic_gas.rs @@ -1,6 +1,8 @@ use anyhow::Result; +use ethereum_types::U256; use crate::cpu::kernel::aggregator::KERNEL; +use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::txn_fields::NormalizedTxnField; use crate::cpu::kernel::interpreter::Interpreter; @@ -14,6 +16,7 @@ fn test_intrinsic_gas() -> Result<()> { // Contract creation transaction. let initial_stack = vec![0xdeadbeefu32.into()]; let mut interpreter = Interpreter::new_with_kernel(intrinsic_gas, initial_stack.clone()); + interpreter.set_global_metadata_field(GlobalMetadata::ContractCreation, U256::one()); interpreter.run()?; assert_eq!(interpreter.stack(), vec![(GAS_TX + GAS_TXCREATE).into()]);