From a327c62c8172bf81501fc193639a078573c98759 Mon Sep 17 00:00:00 2001 From: Niven Date: Tue, 31 Oct 2023 14:05:45 +0800 Subject: [PATCH 1/3] Fix vicinity when creating backend instances, better refactors --- lib/ain-evm/src/core.rs | 97 +++++++++++++++++++++++++------- lib/ain-evm/src/eventlistener.rs | 11 ++-- lib/ain-grpc/src/rpc/debug.rs | 13 +++-- lib/ain-grpc/src/transaction.rs | 6 +- 4 files changed, 97 insertions(+), 30 deletions(-) diff --git a/lib/ain-evm/src/core.rs b/lib/ain-evm/src/core.rs index ca6311c35b..5443eb06d0 100644 --- a/lib/ain-evm/src/core.rs +++ b/lib/ain-evm/src/core.rs @@ -16,16 +16,17 @@ use ethereum::{ TransactionV2, }; use ethereum_types::{Bloom, BloomInput, H160, H256, U256}; -use evm::executor::stack::{MemoryStackState, StackExecutor, StackSubstateMetadata}; -use evm::gasometer::tracing::using as gas_using; -use evm::Config; +use evm::{ + executor::stack::{MemoryStackState, StackExecutor, StackSubstateMetadata}, + gasometer::tracing::using as gas_using, + Config, +}; use evm_runtime::tracing::using as runtime_using; use log::{debug, trace}; use lru::LruCache; use parking_lot::Mutex; use vsdb_core::vsdb_set_base_dir; -use crate::precompiles::MetachainPrecompiles; use crate::{ backend::{BackendError, EVMBackend, Vicinity}, block::INITIAL_BASE_FEE, @@ -33,6 +34,7 @@ use crate::{ executor::{AinExecutor, ExecutorContext, TxResponse}, fee::calculate_max_prepay_gas_fee, gas::check_tx_intrinsic_gas, + precompiles::MetachainPrecompiles, receipt::ReceiptService, storage::{traits::BlockStorage, Storage}, transaction::SignedTx, @@ -273,7 +275,11 @@ impl EVMCoreService { block.header.gas_limit, ) }) - .unwrap_or_default(); + .ok_or(format_err!( + "[call] Block number {:x?} not found", + block_number + ))?; + debug!( "Calling EVM at block number : {:#x}, state_root : {:#x}", block_number, state_root @@ -767,11 +773,29 @@ impl EVMCoreService { access_list: AccessList, block_number: U256, ) -> Result<(Vec, bool, Vec, u64)> { - let (state_root, block_number) = self + let ( + state_root, + block_number, + beneficiary, + base_fee, + timestamp, + block_difficulty, + block_gas_limit, + ) = self .storage .get_block_by_number(&block_number)? .ok_or_else(|| format_err!("Cannot find block")) - .map(|block| (block.header.state_root, block.header.number))?; + .map(|block| { + ( + block.header.state_root, + block.header.number, + block.header.beneficiary, + block.header.base_fee, + block.header.timestamp, + block.header.difficulty, + block.header.gas_limit, + ) + })?; debug!( "Calling EVM at block number : {:#x}, state_root : {:#x}", @@ -779,9 +803,16 @@ impl EVMCoreService { ); let vicinity = Vicinity { - block_number, + gas_price: base_fee, origin: caller, - ..Default::default() + beneficiary, + block_number, + timestamp: U256::from(timestamp), + total_gas_used: U256::zero(), + block_difficulty, + block_gas_limit, + block_base_fee_per_gas: base_fee, + block_randomness: None, }; let backend = EVMBackend::from_root( @@ -921,28 +952,56 @@ impl EVMCoreService { } pub fn get_latest_block_backend(&self) -> Result { - let (state_root, block_number) = self + let ( + state_root, + block_number, + beneficiary, + base_fee, + timestamp, + block_difficulty, + block_gas_limit, + ) = self .storage .get_latest_block()? - .map(|block| (block.header.state_root, block.header.number)) - .unwrap_or_default(); + .map(|block| { + ( + block.header.state_root, + block.header.number, + block.header.beneficiary, + block.header.base_fee, + block.header.timestamp, + block.header.difficulty, + block.header.gas_limit, + ) + }) + .ok_or(format_err!( + "[get_latest_block_backend] Latest block not found", + ))?; trace!( "[get_latest_block_backend] At block number : {:#x}, state_root : {:#x}", block_number, - state_root + state_root, ); + let vicinity = Vicinity { + gas_price: base_fee, + beneficiary, + block_number, + timestamp: U256::from(timestamp), + total_gas_used: U256::zero(), + block_difficulty, + block_gas_limit, + block_base_fee_per_gas: base_fee, + block_randomness: None, + ..Vicinity::default() + }; + EVMBackend::from_root( state_root, Arc::clone(&self.trie_store), Arc::clone(&self.storage), - Vicinity { - block_gas_limit: U256::from( - self.storage.get_attributes_or_default()?.block_gas_limit, - ), - ..Vicinity::default() - }, + vicinity, ) } diff --git a/lib/ain-evm/src/eventlistener.rs b/lib/ain-evm/src/eventlistener.rs index f6d83b4dab..ae2d4b6239 100644 --- a/lib/ain-evm/src/eventlistener.rs +++ b/lib/ain-evm/src/eventlistener.rs @@ -1,10 +1,11 @@ -use crate::core::ExecutionStep; -use crate::opcode; -use evm::gasometer::tracing::{Event as GasEvent, EventListener as GasEventListener}; -use evm_runtime::tracing::{Event as RuntimeEvent, EventListener as RuntimeEventListener}; -use evm_runtime::Opcode; use std::collections::VecDeque; +use crate::{core::ExecutionStep, opcode}; +use evm::gasometer::tracing::{Event as GasEvent, EventListener as GasEventListener}; +use evm_runtime::{ + tracing::{Event as RuntimeEvent, EventListener as RuntimeEventListener}, + Opcode, +}; use log::debug; pub struct Listener { diff --git a/lib/ain-grpc/src/rpc/debug.rs b/lib/ain-grpc/src/rpc/debug.rs index 5af9980fe2..6dd15945c7 100644 --- a/lib/ain-grpc/src/rpc/debug.rs +++ b/lib/ain-grpc/src/rpc/debug.rs @@ -1,10 +1,15 @@ use anyhow::format_err; use std::sync::Arc; -use ain_evm::storage::traits::{ReceiptStorage, TransactionStorage}; -use ain_evm::transaction::SignedTx; use ain_evm::{ - core::EthCallArgs, evm::EVMServices, executor::TxResponse, storage::block_store::DumpArg, + core::EthCallArgs, + evm::EVMServices, + executor::TxResponse, + storage::{ + block_store::DumpArg, + traits::{ReceiptStorage, TransactionStorage}, + }, + transaction::SignedTx, }; use ethereum::Account; use ethereum_types::{H256, U256}; @@ -15,10 +20,10 @@ use jsonrpsee::{ use log::debug; use rlp::{Decodable, Rlp}; -use crate::transaction::{TraceLogs, TraceTransactionResult}; use crate::{ call_request::CallRequest, errors::{to_custom_err, RPCError}, + transaction::{TraceLogs, TraceTransactionResult}, }; #[derive(Serialize, Deserialize)] diff --git a/lib/ain-grpc/src/transaction.rs b/lib/ain-grpc/src/transaction.rs index 0057dd0876..30afb8d5be 100644 --- a/lib/ain-grpc/src/transaction.rs +++ b/lib/ain-grpc/src/transaction.rs @@ -1,5 +1,7 @@ -use ain_evm::core::ExecutionStep; -use ain_evm::transaction::{SignedTx, TransactionError}; +use ain_evm::{ + core::ExecutionStep, + transaction::{SignedTx, TransactionError}, +}; use ethereum::{AccessListItem, BlockAny, EnvelopedEncodable, TransactionV2}; use ethereum_types::{H256, U256}; From 2925f4532b59b98cae6ade8251d58b07bdcff7e6 Mon Sep 17 00:00:00 2001 From: Niven Date: Tue, 31 Oct 2023 14:13:38 +0800 Subject: [PATCH 2/3] Rename to eth debug RPC for cpp exports --- lib/ain-cpp-imports/src/bridge.rs | 4 ++-- lib/ain-cpp-imports/src/lib.rs | 12 ++++++------ lib/ain-grpc/src/rpc/debug.rs | 4 ++-- src/ffi/ffiexports.cpp | 4 ++-- src/ffi/ffiexports.h | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/ain-cpp-imports/src/bridge.rs b/lib/ain-cpp-imports/src/bridge.rs index 10d6585c32..79a1a89130 100644 --- a/lib/ain-cpp-imports/src/bridge.rs +++ b/lib/ain-cpp-imports/src/bridge.rs @@ -50,7 +50,7 @@ pub mod ffi { fn getNumCores() -> i32; fn getCORSAllowedOrigin() -> String; fn getNumConnections() -> i32; - fn isDebugEnabled() -> bool; - fn isDebugTraceEnabled() -> bool; + fn isEthDebugRPCEnabled() -> bool; + fn isEthDebugTraceRPCEnabled() -> bool; } } diff --git a/lib/ain-cpp-imports/src/lib.rs b/lib/ain-cpp-imports/src/lib.rs index 5fd880edf4..9912cf27bd 100644 --- a/lib/ain-cpp-imports/src/lib.rs +++ b/lib/ain-cpp-imports/src/lib.rs @@ -100,10 +100,10 @@ mod ffi { pub fn getNumConnections() -> i32 { unimplemented!("{}", UNIMPL_MSG) } - pub fn isDebugEnabled() -> bool { + pub fn isEthDebugRPCEnabled() -> bool { unimplemented!("{}", UNIMPL_MSG) } - pub fn isDebugTraceEnabled() -> bool { + pub fn isEthDebugTraceRPCEnabled() -> bool { unimplemented!("{}", UNIMPL_MSG) } } @@ -217,12 +217,12 @@ pub fn get_num_connections() -> i32 { ffi::getNumConnections() } -pub fn is_debug_enabled() -> bool { - ffi::isDebugEnabled() +pub fn is_eth_debug_rpc_enabled() -> bool { + ffi::isEthDebugRPCEnabled() } -pub fn is_debug_trace_enabled() -> bool { - ffi::isDebugTraceEnabled() +pub fn is_eth_debug_trace_rpc_enabled() -> bool { + ffi::isEthDebugTraceRPCEnabled() } #[cfg(test)] diff --git a/lib/ain-grpc/src/rpc/debug.rs b/lib/ain-grpc/src/rpc/debug.rs index 6dd15945c7..43ac395a6d 100644 --- a/lib/ain-grpc/src/rpc/debug.rs +++ b/lib/ain-grpc/src/rpc/debug.rs @@ -72,7 +72,7 @@ impl MetachainDebugRPCModule { } fn is_enabled(&self) -> RpcResult<()> { - if !ain_cpp_imports::is_debug_enabled() { + if !ain_cpp_imports::is_eth_debug_rpc_enabled() { return Err(Error::Custom( "debug_* RPCs have not been enabled".to_string(), )); @@ -82,7 +82,7 @@ impl MetachainDebugRPCModule { } fn is_trace_enabled(&self) -> RpcResult<()> { - if !ain_cpp_imports::is_debug_trace_enabled() { + if !ain_cpp_imports::is_eth_debug_trace_rpc_enabled() { return Err(Error::Custom( "debug_trace* RPCs have not been enabled".to_string(), )); diff --git a/src/ffi/ffiexports.cpp b/src/ffi/ffiexports.cpp index 6fa4c7e057..b63bd2ed84 100644 --- a/src/ffi/ffiexports.cpp +++ b/src/ffi/ffiexports.cpp @@ -301,10 +301,10 @@ int32_t getNumConnections() { return (int32_t)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL); } -bool isDebugEnabled() { +bool isEthDebugRPCEnabled() { return gArgs.GetBoolArg("-ethdebug", false); } -bool isDebugTraceEnabled() { +bool isEthDebugTraceRPCEnabled() { return gArgs.GetBoolArg("-ethdebugtrace", true); } diff --git a/src/ffi/ffiexports.h b/src/ffi/ffiexports.h index 23b589f5c0..45e689f19d 100644 --- a/src/ffi/ffiexports.h +++ b/src/ffi/ffiexports.h @@ -74,7 +74,7 @@ rust::string getClientVersion(); int32_t getNumCores(); rust::string getCORSAllowedOrigin(); int32_t getNumConnections(); -bool isDebugEnabled(); -bool isDebugTraceEnabled(); +bool isEthDebugRPCEnabled(); +bool isEthDebugTraceRPCEnabled(); #endif // DEFI_FFI_FFIEXPORTS_H From 2e8dd78528d78b3a0459e07da214f2a1b32eb7af Mon Sep 17 00:00:00 2001 From: Niven Date: Tue, 31 Oct 2023 15:42:24 +0800 Subject: [PATCH 3/3] Clean up setting vicinity pipeline with into impl --- lib/ain-evm/src/backend.rs | 25 +++++- lib/ain-evm/src/core.rs | 142 +++++++--------------------------- lib/ain-evm/src/executor.rs | 2 +- lib/ain-grpc/src/rpc/debug.rs | 16 +--- 4 files changed, 53 insertions(+), 132 deletions(-) diff --git a/lib/ain-evm/src/backend.rs b/lib/ain-evm/src/backend.rs index 46f23501b9..4407126636 100644 --- a/lib/ain-evm/src/backend.rs +++ b/lib/ain-evm/src/backend.rs @@ -5,7 +5,7 @@ use std::{ }; use anyhow::format_err; -use ethereum::{Account, Log}; +use ethereum::{Account, Header, Log}; use ethereum_types::{H160, H256, U256}; use evm::backend::{Apply, ApplyBackend, Backend, Basic}; use hash_db::Hasher as _; @@ -30,18 +30,33 @@ fn is_empty_account(account: &Account) -> bool { #[derive(Default, Debug, Clone)] pub struct Vicinity { - pub gas_price: U256, pub origin: H160, + pub gas_price: U256, + pub total_gas_used: U256, pub beneficiary: H160, pub block_number: U256, pub timestamp: U256, - pub total_gas_used: U256, pub block_difficulty: U256, pub block_gas_limit: U256, pub block_base_fee_per_gas: U256, pub block_randomness: Option, } +impl From
for Vicinity { + fn from(header: Header) -> Self { + Vicinity { + beneficiary: header.beneficiary, + block_number: header.number, + timestamp: U256::from(header.timestamp), + block_difficulty: header.difficulty, + block_gas_limit: header.gas_limit, + block_base_fee_per_gas: header.base_fee, + block_randomness: None, + ..Default::default() + } + } +} + #[derive(Debug, Clone)] struct OverlayData { account: Account, @@ -269,11 +284,13 @@ impl EVMBackend { Ok(self.state.commit().into()) } - pub fn update_vicinity_from_tx(&mut self, tx: &SignedTx) { + pub fn update_vicinity_from_tx(&mut self, tx: &SignedTx) -> Result<()> { self.vicinity = Vicinity { origin: tx.sender, + gas_price: tx.effective_gas_price(self.block_base_fee_per_gas())?, ..self.vicinity }; + Ok(()) } pub fn update_vicinity_with_gas_used(&mut self, gas_used: U256) { diff --git a/lib/ain-evm/src/core.rs b/lib/ain-evm/src/core.rs index 5443eb06d0..5d9dd24bea 100644 --- a/lib/ain-evm/src/core.rs +++ b/lib/ain-evm/src/core.rs @@ -252,51 +252,25 @@ impl EVMCoreService { access_list, block_number, } = arguments; + debug!("[call] caller: {:?}", caller); - let ( - state_root, - block_number, - beneficiary, - base_fee, - timestamp, - block_difficulty, - block_gas_limit, - ) = self + let block_header = self .storage .get_block_by_number(&block_number)? - .map(|block| { - ( - block.header.state_root, - block.header.number, - block.header.beneficiary, - block.header.base_fee, - block.header.timestamp, - block.header.difficulty, - block.header.gas_limit, - ) - }) + .map(|block| block.header) .ok_or(format_err!( "[call] Block number {:x?} not found", block_number ))?; - + let state_root = block_header.state_root; debug!( "Calling EVM at block number : {:#x}, state_root : {:#x}", block_number, state_root ); - debug!("[call] caller: {:?}", caller); - let vicinity = Vicinity { - gas_price, - origin: caller, - beneficiary, - block_number, - timestamp: U256::from(timestamp), - total_gas_used: U256::zero(), - block_difficulty, - block_gas_limit, - block_base_fee_per_gas: base_fee, - block_randomness: None, - }; + + let mut vicinity = Vicinity::from(block_header); + vicinity.gas_price = gas_price; + vicinity.origin = caller; debug!("[call] vicinity: {:?}", vicinity); let mut backend = EVMBackend::from_root( @@ -765,63 +739,38 @@ impl EVMCoreService { #[allow(clippy::too_many_arguments)] pub fn trace_transaction( &self, - caller: H160, - to: H160, - value: U256, - data: &[u8], - gas_limit: u64, - access_list: AccessList, + tx: &SignedTx, block_number: U256, ) -> Result<(Vec, bool, Vec, u64)> { - let ( - state_root, - block_number, - beneficiary, - base_fee, - timestamp, - block_difficulty, - block_gas_limit, - ) = self + let caller = tx.sender; + let to = tx.to().ok_or(format_err!( + "debug_traceTransaction does not support contract creation transactions", + ))?; + let value = tx.value(); + let data = tx.data(); + let gas_limit = u64::try_from(tx.gas_limit())?; + let access_list = tx.access_list(); + + let block_header = self .storage .get_block_by_number(&block_number)? - .ok_or_else(|| format_err!("Cannot find block")) - .map(|block| { - ( - block.header.state_root, - block.header.number, - block.header.beneficiary, - block.header.base_fee, - block.header.timestamp, - block.header.difficulty, - block.header.gas_limit, - ) - })?; - + .ok_or_else(|| format_err!("Block not found")) + .map(|block| block.header)?; + let state_root = block_header.state_root; debug!( "Calling EVM at block number : {:#x}, state_root : {:#x}", block_number, state_root ); - let vicinity = Vicinity { - gas_price: base_fee, - origin: caller, - beneficiary, - block_number, - timestamp: U256::from(timestamp), - total_gas_used: U256::zero(), - block_difficulty, - block_gas_limit, - block_base_fee_per_gas: base_fee, - block_randomness: None, - }; - - let backend = EVMBackend::from_root( + let vicinity = Vicinity::from(block_header); + let mut backend = EVMBackend::from_root( state_root, Arc::clone(&self.trie_store), Arc::clone(&self.storage), vicinity, ) .map_err(|e| format_err!("Could not restore backend {}", e))?; + backend.update_vicinity_from_tx(tx)?; static CONFIG: Config = Config::shanghai(); let metadata = StackSubstateMetadata::new(gas_limit, &CONFIG); @@ -835,7 +784,6 @@ impl EVMCoreService { let mut gas_listener = crate::eventlistener::GasListener::new(); let al = access_list.clone(); - gas_using(&mut gas_listener, move || { let access_list = al .into_iter() @@ -952,51 +900,21 @@ impl EVMCoreService { } pub fn get_latest_block_backend(&self) -> Result { - let ( - state_root, - block_number, - beneficiary, - base_fee, - timestamp, - block_difficulty, - block_gas_limit, - ) = self + let block_header = self .storage .get_latest_block()? - .map(|block| { - ( - block.header.state_root, - block.header.number, - block.header.beneficiary, - block.header.base_fee, - block.header.timestamp, - block.header.difficulty, - block.header.gas_limit, - ) - }) + .map(|block| block.header) .ok_or(format_err!( "[get_latest_block_backend] Latest block not found", ))?; - + let state_root = block_header.state_root; trace!( "[get_latest_block_backend] At block number : {:#x}, state_root : {:#x}", - block_number, + block_header.number, state_root, ); - let vicinity = Vicinity { - gas_price: base_fee, - beneficiary, - block_number, - timestamp: U256::from(timestamp), - total_gas_used: U256::zero(), - block_difficulty, - block_gas_limit, - block_base_fee_per_gas: base_fee, - block_randomness: None, - ..Vicinity::default() - }; - + let vicinity = Vicinity::from(block_header); EVMBackend::from_root( state_root, Arc::clone(&self.trie_store), diff --git a/lib/ain-evm/src/executor.rs b/lib/ain-evm/src/executor.rs index e13e748977..ee74d9e280 100644 --- a/lib/ain-evm/src/executor.rs +++ b/lib/ain-evm/src/executor.rs @@ -147,7 +147,7 @@ impl<'backend> AinExecutor<'backend> { base_fee: U256, system_tx: bool, ) -> Result<(TxResponse, ReceiptV3)> { - self.backend.update_vicinity_from_tx(signed_tx); + self.backend.update_vicinity_from_tx(signed_tx)?; trace!( "[Executor] Executing EVM TX with vicinity : {:?}", self.backend.vicinity diff --git a/lib/ain-grpc/src/rpc/debug.rs b/lib/ain-grpc/src/rpc/debug.rs index 43ac395a6d..538278d32e 100644 --- a/lib/ain-grpc/src/rpc/debug.rs +++ b/lib/ain-grpc/src/rpc/debug.rs @@ -1,4 +1,3 @@ -use anyhow::format_err; use std::sync::Arc; use ain_evm::{ @@ -119,21 +118,8 @@ impl MetachainDebugRPCServer for MetachainDebugRPCModule { let (logs, succeeded, return_data, gas_used) = self .handler .core - .trace_transaction( - signed_tx.sender, - signed_tx.to().ok_or_else(|| { - format_err!( - "debug_traceTransaction does not support contract creation transactions" - ) - })?, - signed_tx.value(), - signed_tx.data(), - signed_tx.gas_limit().as_u64(), - signed_tx.access_list(), - receipt.block_number, - ) + .trace_transaction(&signed_tx, receipt.block_number) .map_err(|e| Error::Custom(format!("Error calling EVM : {e:?}")))?; - let trace_logs = logs.iter().map(|x| TraceLogs::from(x.clone())).collect(); Ok(TraceTransactionResult {