From 15e9c6a189f9fd08dacfd60d9175ddbcd6f162f7 Mon Sep 17 00:00:00 2001 From: Grigoriy Simonov Date: Fri, 14 Apr 2023 12:26:29 +0000 Subject: [PATCH] feat: use storage for pending logs Allow outer code to inject logs for currently running ethereum transaction. --- frame/ethereum/src/lib.rs | 81 +++++++++++++++++++---------------- frame/evm/src/lib.rs | 20 +++++++++ frame/evm/src/runner/stack.rs | 54 ++++++++++------------- primitives/evm/src/lib.rs | 1 - 4 files changed, 86 insertions(+), 70 deletions(-) diff --git a/frame/ethereum/src/lib.rs b/frame/ethereum/src/lib.rs index 72e47a4c6a..7fae5710eb 100644 --- a/frame/ethereum/src/lib.rs +++ b/frame/ethereum/src/lib.rs @@ -48,7 +48,7 @@ use frame_support::{ weights::Weight, }; use frame_system::{pallet_prelude::OriginFor, CheckWeight, WeightInfo}; -use pallet_evm::{BlockHashMapping, FeeCalculator, GasWeightMapping, Runner}; +use pallet_evm::{BlockHashMapping, CurrentLogs, FeeCalculator, GasWeightMapping, Runner}; use sp_runtime::{ generic::DigestItem, traits::{DispatchInfoOf, Dispatchable, One, Saturating, UniqueSaturatedInto, Zero}, @@ -222,6 +222,7 @@ pub mod pallet { )); } Pending::::kill(); + assert_eq!(>::get().len(), 0, "fake transaction finalizer is not initialized, as some logs was left after block is finished"); } fn on_initialize(_: T::BlockNumber) -> Weight { @@ -405,7 +406,7 @@ impl Pallet { } }; cumulative_gas_used = used_gas; - Self::logs_bloom(logs, &mut logs_bloom); + Self::logs_bloom(logs.iter(), &mut logs_bloom); } let ommers = Vec::::new(); @@ -459,10 +460,10 @@ impl Pallet { } } - fn logs_bloom(logs: Vec, bloom: &mut Bloom) { + fn logs_bloom<'a>(logs: impl IntoIterator, bloom: &'a mut Bloom) { for log in logs { bloom.accrue(BloomInput::Raw(&log.address[..])); - for topic in log.topics { + for topic in &log.topics { bloom.accrue(BloomInput::Raw(&topic[..])); } } @@ -546,42 +547,48 @@ impl Pallet { let transaction_index = pending.len() as u32; let (reason, status, used_gas, dest) = match info { - CallOrCreateInfo::Call(info) => ( - info.exit_reason, - TransactionStatus { - transaction_hash, - transaction_index, - from: source, - to, - contract_address: None, - logs: info.logs.clone(), - logs_bloom: { - let mut bloom: Bloom = Bloom::default(); - Self::logs_bloom(info.logs, &mut bloom); - bloom + CallOrCreateInfo::Call(info) => { + let logs = >::take(); + ( + info.exit_reason, + TransactionStatus { + transaction_hash, + transaction_index, + from: source, + to, + contract_address: None, + logs_bloom: { + let mut bloom: Bloom = Bloom::default(); + Self::logs_bloom(logs.iter(), &mut bloom); + bloom + }, + logs, }, - }, - info.used_gas, - to, - ), - CallOrCreateInfo::Create(info) => ( - info.exit_reason, - TransactionStatus { - transaction_hash, - transaction_index, - from: source, + info.used_gas, to, - contract_address: Some(info.value), - logs: info.logs.clone(), - logs_bloom: { - let mut bloom: Bloom = Bloom::default(); - Self::logs_bloom(info.logs, &mut bloom); - bloom + ) + } + CallOrCreateInfo::Create(info) => { + let logs = >::take(); + ( + info.exit_reason, + TransactionStatus { + transaction_hash, + transaction_index, + from: source, + to, + contract_address: Some(info.value), + logs_bloom: { + let mut bloom: Bloom = Bloom::default(); + Self::logs_bloom(logs.iter(), &mut bloom); + bloom + }, + logs, }, - }, - info.used_gas, - Some(info.value), - ), + info.used_gas, + Some(info.value), + ) + } }; let receipt = { diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 19791f5b59..42e0022f3d 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -510,6 +510,11 @@ pub mod pallet { #[pallet::getter(fn account_storages)] pub type AccountStorages = StorageDoubleMap<_, Blake2_128Concat, H160, Blake2_128Concat, H256, H256, ValueQuery>; + + /// Written on log, reset after transaction + /// Should be empty between transactions + #[pallet::storage] + pub type CurrentLogs = StorageValue<_, Vec, ValueQuery>; } /// Type alias for currency balance. @@ -733,6 +738,21 @@ impl Pallet { >::insert(address, code); } + /// Add log to be injected in either real or fake ethereum transaction + pub fn deposit_log(log: Log) { + log::trace!( + target: "evm", + "Inserting mirrored log for {:?}, topics ({}) {:?}, data ({}): {:?}]", + log.address, + log.topics.len(), + log.topics, + log.data.len(), + log.data + ); + >::append(log); + // Log event is not emitted here, as these logs belong to pallets, which will emit pallet-specific logs on substrate side by themselves + } + /// Get the account basic in EVM format. pub fn account_basic(address: &H160) -> (Account, frame_support::weights::Weight) { let account_id = T::AddressMapping::into_account_id(*address); diff --git a/frame/evm/src/runner/stack.rs b/frame/evm/src/runner/stack.rs index 3193b1c049..74793a1f6b 100644 --- a/frame/evm/src/runner/stack.rs +++ b/frame/evm/src/runner/stack.rs @@ -19,8 +19,8 @@ use crate::{ runner::Runner as RunnerT, AccountCodes, AccountStorages, AddressMapping, BalanceOf, - BlockHashMapping, Config, Error, Event, FeeCalculator, OnChargeEVMTransaction, OnCreate, - Pallet, RunnerError, + BlockHashMapping, Config, CurrentLogs, Error, Event, FeeCalculator, OnChargeEVMTransaction, + OnCreate, Pallet, RunnerError, }; use evm::{ backend::Backend as BackendT, @@ -261,30 +261,10 @@ where Pallet::::remove_account(&address) } - for log in &state.substate.logs { - log::trace!( - target: "evm", - "Inserting log for {:?}, topics ({}) {:?}, data ({}): {:?}]", - log.address, - log.topics.len(), - log.topics, - log.data.len(), - log.data - ); - Pallet::::deposit_event(Event::::Log { - log: Log { - address: log.address, - topics: log.topics.clone(), - data: log.data.clone(), - }, - }); - } - Ok(ExecutionInfo { value: retv, exit_reason: reason, used_gas, - logs: state.substate.logs, }) } } @@ -486,14 +466,14 @@ where } } -struct SubstrateStackSubstate<'config> { +struct SubstrateStackSubstate<'config, T> { metadata: StackSubstateMetadata<'config>, deletes: BTreeSet, - logs: Vec, - parent: Option>>, + parent: Option>>, + _marker: PhantomData, } -impl<'config> SubstrateStackSubstate<'config> { +impl<'config, T: Config> SubstrateStackSubstate<'config, T> { pub fn metadata(&self) -> &StackSubstateMetadata<'config> { &self.metadata } @@ -507,7 +487,7 @@ impl<'config> SubstrateStackSubstate<'config> { metadata: self.metadata.spit_child(gas_limit, is_static), parent: None, deletes: BTreeSet::new(), - logs: Vec::new(), + _marker: PhantomData, }; mem::swap(&mut entering, self); @@ -521,7 +501,6 @@ impl<'config> SubstrateStackSubstate<'config> { mem::swap(&mut exited, self); self.metadata.swallow_commit(exited.metadata)?; - self.logs.append(&mut exited.logs); self.deletes.append(&mut exited.deletes); sp_io::storage::commit_transaction(); @@ -563,11 +542,22 @@ impl<'config> SubstrateStackSubstate<'config> { } pub fn log(&mut self, address: H160, topics: Vec, data: Vec) { - self.logs.push(Log { + let log = Log { address, topics, data, - }); + }; + log::trace!( + target: "evm", + "Inserting log for {:?}, topics ({}) {:?}, data ({}): {:?}]", + log.address, + log.topics.len(), + log.topics, + log.data.len(), + log.data + ); + >::append(&log); + >::deposit_event(Event::::Log { log }); } fn recursive_is_cold bool>(&self, f: &F) -> bool { @@ -586,7 +576,7 @@ impl<'config> SubstrateStackSubstate<'config> { /// Substrate backend for EVM. pub struct SubstrateStackState<'vicinity, 'config, T> { vicinity: &'vicinity Vicinity, - substate: SubstrateStackSubstate<'config>, + substate: SubstrateStackSubstate<'config, T>, original_storage: BTreeMap<(H160, H256), H256>, _marker: PhantomData, } @@ -599,8 +589,8 @@ impl<'vicinity, 'config, T: Config> SubstrateStackState<'vicinity, 'config, T> { substate: SubstrateStackSubstate { metadata, deletes: BTreeSet::new(), - logs: Vec::new(), parent: None, + _marker: PhantomData, }, _marker: PhantomData, original_storage: BTreeMap::new(), diff --git a/primitives/evm/src/lib.rs b/primitives/evm/src/lib.rs index b7e8e38741..a85872e12d 100644 --- a/primitives/evm/src/lib.rs +++ b/primitives/evm/src/lib.rs @@ -62,7 +62,6 @@ pub struct ExecutionInfo { pub exit_reason: ExitReason, pub value: T, pub used_gas: U256, - pub logs: Vec, } pub type CallInfo = ExecutionInfo>;