From ffd3d7c294e91d18c5723a580004b38960cebe1a Mon Sep 17 00:00:00 2001 From: Jouzo <15011228+Jouzo@users.noreply.github.com> Date: Mon, 15 May 2023 13:27:29 +0100 Subject: [PATCH] Add vinicity to EVM execution and update on each TX (#1987) --- lib/ain-evm/src/backend.rs | 73 +++++++++++++++++++++++++------------ lib/ain-evm/src/evm.rs | 16 +++++--- lib/ain-evm/src/executor.rs | 37 +++++++++++-------- lib/ain-evm/src/handler.rs | 17 ++++++--- 4 files changed, 93 insertions(+), 50 deletions(-) diff --git a/lib/ain-evm/src/backend.rs b/lib/ain-evm/src/backend.rs index 6aae6816a3..2b08a03f86 100644 --- a/lib/ain-evm/src/backend.rs +++ b/lib/ain-evm/src/backend.rs @@ -1,14 +1,19 @@ use ethereum::{Account, Log}; use evm::backend::{Apply, ApplyBackend, Backend, Basic}; use hash_db::Hasher as _; -use log::debug; +use log::{debug, trace}; use primitive_types::{H160, H256, U256}; use rlp::{Decodable, Encodable, Rlp}; use sp_core::hexdisplay::AsBytesRef; use sp_core::Blake2Hasher; use vsdb_trie_db::MptOnce; -use crate::{evm::TrieDBStore, storage::Storage, traits::BridgeBackend}; +use crate::{ + evm::TrieDBStore, + storage::{traits::BlockStorage, Storage}, + traits::BridgeBackend, + transaction::SignedTx, +}; type Hasher = Blake2Hasher; @@ -16,14 +21,22 @@ fn is_empty_account(account: &Account) -> bool { account.balance.is_zero() && account.nonce.is_zero() && account.code_hash.is_zero() } -// TBD -pub struct Vicinity; +#[derive(Default, Debug)] +pub struct Vicinity { + pub gas_price: U256, + pub origin: H160, + pub beneficiary: H160, + pub block_number: U256, + pub timestamp: U256, + pub gas_limit: U256, + pub block_base_fee_per_gas: U256, +} pub struct EVMBackend { state: MptOnce, trie_store: Arc, storage: Arc, - _vicinity: Vicinity, + pub vicinity: Vicinity, } type Result = std::result::Result; @@ -33,7 +46,7 @@ impl EVMBackend { state_root: H256, trie_store: Arc, storage: Arc, - _vicinity: Vicinity, + vicinity: Vicinity, ) -> Result { let state = trie_store .trie_db @@ -44,7 +57,7 @@ impl EVMBackend { state, trie_store, storage, - _vicinity, + vicinity, }) } @@ -104,6 +117,15 @@ impl EVMBackend { pub fn commit(&mut self) -> H256 { self.state.commit().into() } + + pub fn update_vicinity_from_tx(&mut self, tx: &SignedTx) { + self.vicinity = Vicinity { + origin: tx.sender, + gas_price: tx.gas_price(), + gas_limit: tx.gas_limit(), + ..self.vicinity + }; + } } impl EVMBackend { @@ -117,29 +139,33 @@ impl EVMBackend { impl Backend for EVMBackend { fn gas_price(&self) -> U256 { - debug!(target: "backend", "[EVMBackend] Getting gas"); - unimplemented!() + trace!(target: "backend", "[EVMBackend] Getting gas"); + self.vicinity.gas_price } fn origin(&self) -> H160 { - debug!(target: "backend", "[EVMBackend] Getting origin"); - unimplemented!() + trace!(target: "backend", "[EVMBackend] Getting origin"); + self.vicinity.origin } - fn block_hash(&self, _number: U256) -> H256 { - unimplemented!("Implement block_hash function") + fn block_hash(&self, number: U256) -> H256 { + trace!(target: "backend", "[EVMBackend] Getting block hash for block {:x?}", number); + self.storage + .get_block_by_number(&number) + .map_or(H256::zero(), |block| block.header.hash()) } fn block_number(&self) -> U256 { - unimplemented!() + trace!(target: "backend", "[EVMBackend] Getting current block number"); + self.vicinity.block_number } fn block_coinbase(&self) -> H160 { - unimplemented!("Implement block_coinbase function") + self.vicinity.beneficiary } fn block_timestamp(&self) -> U256 { - unimplemented!("Implement block_timestamp function") + self.vicinity.timestamp } fn block_difficulty(&self) -> U256 { @@ -147,13 +173,12 @@ impl Backend for EVMBackend { } fn block_gas_limit(&self) -> U256 { - unimplemented!("Implement block_gas_limit function") + self.vicinity.gas_limit } fn block_base_fee_per_gas(&self) -> U256 { - debug!(target: "backend", "[EVMBackend] Getting block_base_fee_per_gas"); - U256::default() - // unimplemented!("Implement block_base_fee_per_gas function") + trace!(target: "backend", "[EVMBackend] Getting block_base_fee_per_gas"); + self.vicinity.block_base_fee_per_gas } fn chain_id(&self) -> U256 { @@ -165,7 +190,7 @@ impl Backend for EVMBackend { } fn basic(&self, address: H160) -> Basic { - debug!(target: "backend", "[EVMBackend] basic for address {:x?}", address); + trace!(target: "backend", "[EVMBackend] basic for address {:x?}", address); self.get_account(address) .map(|account| Basic { balance: account.balance, @@ -175,14 +200,14 @@ impl Backend for EVMBackend { } fn code(&self, address: H160) -> Vec { - debug!(target: "backend", "[EVMBackend] code for address {:x?}", address); + trace!(target: "backend", "[EVMBackend] code for address {:x?}", address); self.get_account(address) .and_then(|account| self.storage.get_code_by_hash(account.code_hash)) .unwrap_or_default() } fn storage(&self, address: H160, index: H256) -> H256 { - debug!(target: "backend", "[EVMBackend] Getting storage for address {:x?} at index {:x?}", address, index); + trace!(target: "backend", "[EVMBackend] Getting storage for address {:x?} at index {:x?}", address, index); self.get_account(address) .and_then(|account| { self.trie_store @@ -196,7 +221,7 @@ impl Backend for EVMBackend { } fn original_storage(&self, address: H160, index: H256) -> Option { - debug!(target: "backend", "[EVMBackend] Getting original storage for address {:x?} at index {:x?}", address, index); + trace!(target: "backend", "[EVMBackend] Getting original storage for address {:x?} at index {:x?}", address, index); Some(self.storage(address, index)) } } diff --git a/lib/ain-evm/src/evm.rs b/lib/ain-evm/src/evm.rs index c50c85b50a..07d8e425a2 100644 --- a/lib/ain-evm/src/evm.rs +++ b/lib/ain-evm/src/evm.rs @@ -99,13 +99,20 @@ impl EVMHandler { gas_limit: u64, access_list: AccessList, ) -> Result> { - let state_root = self + let (state_root, block_number) = self .storage .get_latest_block() - .map(|block| block.header.state_root) + .map(|block| (block.header.state_root, block.header.number)) .unwrap_or_default(); println!("state_root : {:#?}", state_root); - let vicinity = Vicinity {}; + + let vicinity = Vicinity { + block_number, + origin: caller.unwrap_or_default(), + gas_limit: U256::from(gas_limit), + ..Default::default() + }; + let mut backend = EVMBackend::from_root( state_root, Arc::clone(&self.trie_store), @@ -251,13 +258,12 @@ impl EVMHandler { .or_else(|| self.storage.get_latest_block()) .map(|block| block.header.state_root) .unwrap_or_default(); - let vicinity = Vicinity {}; let backend = EVMBackend::from_root( state_root, Arc::clone(&self.trie_store), Arc::clone(&self.storage), - vicinity, + Vicinity::default(), )?; Ok(backend.get_account(address)) } diff --git a/lib/ain-evm/src/executor.rs b/lib/ain-evm/src/executor.rs index d96376a2cb..e6a274ee88 100644 --- a/lib/ain-evm/src/executor.rs +++ b/lib/ain-evm/src/executor.rs @@ -1,5 +1,5 @@ use crate::{ - backend::EVMBackendError, + backend::{EVMBackend, EVMBackendError}, evm::EVMHandler, traits::{BridgeBackend, Executor, ExecutorContext}, transaction::SignedTx, @@ -7,23 +7,22 @@ use crate::{ use ethereum::{EIP658ReceiptData, Log, ReceiptV3}; use ethereum_types::{Bloom, U256}; use evm::{ - backend::{ApplyBackend, Backend}, + backend::ApplyBackend, executor::stack::{MemoryStackState, StackExecutor, StackSubstateMetadata}, Config, ExitReason, }; -use primitive_types::H160; +use log::trace; +use primitive_types::{H160, H256}; use std::collections::BTreeMap; -#[derive(Debug)] -pub struct AinExecutor<'backend, B: Backend> { - pub backend: &'backend mut B, +pub struct AinExecutor<'backend> { + backend: &'backend mut EVMBackend, } -impl<'backend, B> AinExecutor<'backend, B> -where - B: Backend + ApplyBackend + BridgeBackend, -{ - pub fn new(backend: &'backend mut B) -> Self { +impl<'backend> AinExecutor<'backend> {} + +impl<'backend> AinExecutor<'backend> { + pub fn new(backend: &'backend mut EVMBackend) -> Self { Self { backend } } @@ -34,12 +33,13 @@ where pub fn sub_balance(&mut self, address: H160, amount: U256) -> Result<(), EVMBackendError> { self.backend.sub_balance(address, amount) } + + pub fn commit(&mut self) -> H256 { + self.backend.commit() + } } -impl<'backend, B> Executor for AinExecutor<'backend, B> -where - B: Backend + ApplyBackend, -{ +impl<'backend> Executor for AinExecutor<'backend> { const CONFIG: Config = Config::london(); fn call(&mut self, ctx: ExecutorContext, apply: bool) -> TxResponse { @@ -74,7 +74,7 @@ where let (values, logs) = executor.into_state().deconstruct(); let logs = logs.into_iter().collect::>(); if apply && exit_reason.is_succeed() { - self.backend.apply(values, logs.clone(), true); + ApplyBackend::apply(self.backend, values, logs.clone(), true); } let receipt = ReceiptV3::EIP1559(EIP658ReceiptData { @@ -99,6 +99,11 @@ where fn exec(&mut self, signed_tx: &SignedTx) -> TxResponse { let apply = true; + self.backend.update_vicinity_from_tx(signed_tx); + trace!( + "[Executor] Executing EVM TX with vicinity : {:?}", + self.backend.vicinity + ); self.call( ExecutorContext { caller: Some(signed_tx.sender), diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index c34f62f1a0..fe0e8a7bb3 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -57,6 +57,7 @@ impl Handlers { let mut gas_used = 0u64; let mut logs_bloom: Bloom = Bloom::default(); + let (parent_hash, parent_number) = self.block.get_latest_block_hash_and_number(); let state_root = self .storage .get_latest_block() @@ -64,7 +65,12 @@ impl Handlers { block.header.state_root }); - let vicinity = Vicinity {}; + let vicinity = Vicinity { + beneficiary, + timestamp: U256::from(timestamp), + block_number: parent_number + 1, + ..Default::default() + }; let mut backend = EVMBackend::from_root( state_root, @@ -101,7 +107,7 @@ impl Handlers { EVMHandler::logs_bloom(logs, &mut logs_bloom); receipts_v3.push(receipt); - executor.backend.commit(); + executor.commit(); } QueueTx::BridgeTx(BridgeTx::EvmIn(BalanceUpdate { address, amount })) => { debug!( @@ -129,8 +135,6 @@ impl Handlers { self.evm.tx_queues.remove(context); - let (parent_hash, parent_number) = self.block.get_latest_block_hash_and_number(); - let block = Block::new( PartialHeader { parent_hash, @@ -166,7 +170,10 @@ impl Handlers { ); if update_state { - debug!("new_state_root : {:#x}", block.header.state_root); + debug!( + "[finalize_block] Updating state with new state_root : {:#x}", + block.header.state_root + ); self.block.connect_block(block.clone()); self.receipt.put_receipts(receipts); }