From d20b5cf0e3cf0cdcdaaa26aebb55b41758a39198 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 28 Oct 2025 11:59:30 +0100 Subject: [PATCH 1/4] introduce inherent handler in pallet revive --- .../frame/revive/rpc/src/receipt_extractor.rs | 120 ++++++++++++++---- .../frame/revive/src/inherent_handlers.rs | 60 +++++++++ substrate/frame/revive/src/lib.rs | 87 ++++++++++++- 3 files changed, 244 insertions(+), 23 deletions(-) create mode 100644 substrate/frame/revive/src/inherent_handlers.rs diff --git a/substrate/frame/revive/rpc/src/receipt_extractor.rs b/substrate/frame/revive/rpc/src/receipt_extractor.rs index 5569a1940c109..5ee1d6b17876b 100644 --- a/substrate/frame/revive/rpc/src/receipt_extractor.rs +++ b/substrate/frame/revive/rpc/src/receipt_extractor.rs @@ -18,7 +18,7 @@ use crate::{ client::{SubstrateBlock, SubstrateBlockNumber}, subxt_client::{ self, - revive::{calls::types::EthTransact, events::ContractEmitted}, + revive::{calls::types::{EthTransact, SystemLogDispatch}, events::ContractEmitted}, system::events::ExtrinsicSuccess, transaction_payment::events::TransactionFeePaid, SrcChainConfig, @@ -32,7 +32,7 @@ use pallet_revive::{ }; use sp_core::keccak_256; use std::{future::Future, pin::Pin, sync::Arc}; -use subxt::OnlineClient; +use subxt::{blocks, OnlineClient}; type FetchGasPriceFn = Arc< dyn Fn(H256) -> Pin> + Send>> + Send + Sync, @@ -131,7 +131,7 @@ impl ReceiptExtractor { async fn extract_from_extrinsic( &self, block: &SubstrateBlock, - ext: subxt::blocks::ExtrinsicDetails>, + ext: &subxt::blocks::ExtrinsicDetails>, call: EthTransact, ) -> Result<(TransactionSigned, ReceiptInfo), ClientError> { let transaction_index = ext.index(); @@ -217,6 +217,74 @@ impl ReceiptExtractor { Ok((signed_tx, receipt)) } + /// Extract a [`TransactionSigned`] and a [`ReceiptInfo`] from a System Log extrinsic. + async fn extract_from_system_log( + &self, + block: &SubstrateBlock, + ext: &subxt::blocks::ExtrinsicDetails>, + _call: SystemLogDispatch, + ) -> Result<(TransactionSigned, ReceiptInfo), ClientError> { + let transaction_index = ext.index(); + let block_number = U256::from(block.number()); + let block_hash = block.hash(); + + let events = ext.events().await?; + + let success = events.has::().inspect_err(|err| { + log::debug!(target: LOG_TARGET, "Failed to lookup for ExtrinsicSuccess event in block {block_number}: {err:?}") + })?; + + let transaction_hash = ext.hash(); + + let signed_tx = TransactionSigned::default(); + let from = H160::zero(); + let gas_price = U256::zero(); + let gas_used = U256::zero(); + + let logs = events + .iter() + .filter_map(|event_details| { + let event_details = event_details.ok()?; + let event = event_details.as_event::().ok()??; + + Some( Log { + address: event.contract, + block_hash, + block_number, + data: Some(event.data.into()), + log_index: event_details.index().into(), + topics: event.topics, + transaction_hash, + transaction_index: transaction_index.into(), + ..Default::default() + }) + }).collect(); + + let contract_adddress = None; + let to_address = None; + + let tx_type: pallet_revive::evm::Byte = pallet_revive::evm::Byte(0u8); + + let receipt = ReceiptInfo::new( + block_hash, + block_number, + contract_adddress, + from, + logs, + to_address, + gas_price, + gas_used, + success, + transaction_hash, + transaction_index.into(), + tx_type + ); + + Ok((signed_tx, receipt)) + + + } + /// Extract receipts from block. pub async fn extract_from_block( &self, @@ -231,22 +299,27 @@ impl ReceiptExtractor { log::debug!(target: LOG_TARGET, "Error fetching for #{:?} extrinsics: {err:?}", block.number()); })?; - let extrinsics = extrinsics.iter().flat_map(|ext| { - let call = ext.as_extrinsic::().ok()??; - Some((ext, call)) - }); + let mut results = Vec::new(); + for ext in extrinsics.iter() { + if let Some(call) = ext.as_extrinsic::().ok().flatten() { + match self.extract_from_extrinsic(block, &ext, call).await { + Ok(receipt_info) => results.push(Ok(receipt_info)), + Err(e) => { + log::warn!(target: LOG_TARGET, "Error extracting EthTransact extrinsic: {e:?}"); + } + } + } + else if let Some(call) = ext.as_extrinsic::().ok().flatten() { + match self.extract_from_system_log(block, &ext, call).await { + Ok(receipt_info) => results.push(Ok(receipt_info)), + Err(e) => { + log::warn!(target: LOG_TARGET, "Error extracting SystemLogDispatch extrinsic: {e:?}"); + } + } + } + } - stream::iter(extrinsics) - .map(|(ext, call)| async move { - self.extract_from_extrinsic(block, ext, call).await.inspect_err(|err| { - log::warn!(target: LOG_TARGET, "Error extracting extrinsic: {err:?}"); - }) - }) - .buffer_unordered(10) - .collect::>>() - .await - .into_iter() - .collect::, _>>() + results.into_iter().collect::, _>>() } /// Extract receipt from transaction @@ -261,9 +334,12 @@ impl ReceiptExtractor { .nth(transaction_index) .ok_or(ClientError::EthExtrinsicNotFound)?; - let call = ext - .as_extrinsic::()? - .ok_or_else(|| ClientError::EthExtrinsicNotFound)?; - self.extract_from_extrinsic(block, ext, call).await + if let Some(call) = ext.as_extrinsic::().ok().flatten() { + self.extract_from_extrinsic(block, &ext, call).await + } else if let Some(call) = ext.as_extrinsic::().ok().flatten() { + self.extract_from_system_log(block, &ext, call).await + } else { + Err(ClientError::EthExtrinsicNotFound) + } } } diff --git a/substrate/frame/revive/src/inherent_handlers.rs b/substrate/frame/revive/src/inherent_handlers.rs new file mode 100644 index 0000000000000..a3008e6074ebc --- /dev/null +++ b/substrate/frame/revive/src/inherent_handlers.rs @@ -0,0 +1,60 @@ +use alloc::vec::Vec; +use impl_trait_for_tuples::impl_for_tuples; +use sp_runtime::{DispatchError, DispatchResult}; +use crate::InherentHandlerMessage; + +/// Defines the interface for a pallet capable of handling a specific type of inherent system message. +/// +/// Pallets implementing this trait register themselves as potential handlers for messages +/// identified by a unique `name`. +pub trait InherentHandler { + /// A unique identifier for this handler + fn handler_name() -> &'static [u8]; + + /// The function that processes the raw message byte intended for this handler. + fn handle_message(message: Vec) -> DispatchResult; +} + +/// Defines the interface for a collection(tuple) of `InherentHandler` +/// +/// This trait provides functions to validate handler names and dispatch mesaages to the +/// appropriate handler within the collection. +pub trait InherentHandlers { + /// Checks if a handler with the given `name` exists within this collection. + /// + /// Used during unsigned transaction validation(`ValidateUnsigned`) to ensure the targe handler is known before accepting the extrinsic. + fn is_valid_handler(name: &[u8]) -> bool; + + /// Finds the handler matching the `handler_name` within the message and call its `handle_message` + fn dispatch_message(message: InherentHandlerMessage) -> DispatchResult; +} + + +/// Base case implementation for an empty tuple `()` +impl InherentHandlers for () { + fn is_valid_handler(_name: &[u8]) -> bool { + false + } + + fn dispatch_message(_message: InherentHandlerMessage) -> DispatchResult { + Err(DispatchError::Other("No matching inherent handler found")) + } +} + +/// Recursive implementation for a non-empty tuple up to 8 elements . +#[impl_for_tuples(1, 8)] +#[tuple_types_custom_trait_bound(InherentHandler)] +impl InherentHandlers for Tuple { + fn is_valid_handler(name: &[u8]) -> bool { + for_tuples!( #( if Tuple::handler_name() == name { return true; } )* ); + false + } + + fn dispatch_message(message: InherentHandlerMessage) -> DispatchResult { + let handler_name = message.handler_name.as_slice(); + for_tuples!( #( if Tuple::handler_name() == handler_name { + return Tuple::handle_message(message.raw_message); + } )* ); + Err(DispatchError::Other("No matching inherent handler found")) + } +} \ No newline at end of file diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 694f1e2899ce3..21c8463bdee65 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -44,6 +44,7 @@ pub mod precompiles; pub mod test_utils; pub mod tracing; pub mod weights; +pub mod inherent_handlers; use crate::{ evm::{ @@ -55,13 +56,14 @@ use crate::{ }, exec::{AccountIdOf, ExecError, Executable, Stack as ExecStack}, gas::GasMeter, + inherent_handlers::{InherentHandler, InherentHandlers}, storage::{meter::Meter as StorageMeter, AccountType, DeletionQueueManager}, tracing::if_tracing, vm::{pvm::extract_code_and_data, CodeInfo, ContractBlob, RuntimeCosts}, weightinfo_extension::OnFinalizeBlockParts, }; use alloc::{boxed::Box, format, vec}; -use codec::{Codec, Decode, Encode}; +use codec::{Codec, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use environmental::*; use frame_support::{ dispatch::{ @@ -115,6 +117,25 @@ type TrieId = BoundedVec>; type ImmutableData = BoundedVec>; type CallOf = ::RuntimeCall; +/// Represents a message intended for routing to a specific `InherentHandler`. +/// +/// This struct wraps the raw message payload alongside the name of the handler +/// designated to process it. It's used as the argument for the +/// `system_log_dispatch` extrinsic in `pallet-revive`. +#[derive(Debug, Clone, PartialEq, Eq, DecodeWithMemTracking, Encode, Decode, TypeInfo)] +pub struct InherentHandlerMessage { + /// The unique byte slice identifier of the target `InherentHandler`. + /// + /// This name is used by the `InherentHandlers` dispatch logic to find the + /// correct handler pallet. e.g: `b"hyperbridge_proof_verifier_v1"`. + pub handler_name: Vec, + /// The raw byte payload of the message. + /// + /// This data will be passed to the `handle_message` function of the + /// designated handler. Its internal format is specific to the handler. + pub raw_message: Vec +} + /// Used as a sentinel value when reading and writing contract memory. /// /// It is usually used to signal `None` to a contract when only a primitive is allowed @@ -332,6 +353,23 @@ pub mod pallet { /// Allows debug-mode configuration, such as enabling unlimited contract size. #[pallet::constant] type DebugEnabled: Get; + + /// Specifies the type responsible for dispatching inherent system log messages. + /// + /// This type must implement the [`inherent_handlers::InherentHandlers`] trait, which provides + /// the logic for validating handler names (`is_valid_handler`) and routing messages + /// (`dispatch_message`). + /// + /// In the runtime, this is typically configured as a tuple containing the specific + /// pallets that implement the [`inherent_handlers::InherentHandler`] trait. + /// + /// e,g Runtime Configuration: + /// ```ignore + /// type InherentHandlers = ( + /// hyperbridge_ismp-parachain::Pallet, + /// ); + /// ``` + type InherentHandlers: InherentHandlers; } /// Container for different types that implement [`DefaultConfig`]` of this pallet. @@ -414,6 +452,8 @@ pub mod pallet { type FeeInfo = (); type MaxEthExtrinsicWeight = MaxEthExtrinsicWeight; type DebugEnabled = ConstBool; + + type InherentHandlers = (); } } @@ -1440,6 +1480,49 @@ pub mod pallet { T::AddressMapper::to_fallback_account_id(&T::AddressMapper::to_address(&origin)); call.dispatch(RawOrigin::Signed(unmapped_account).into()) } + + /// Dispatches a system log message to the appropriate `InherentHandler`. + /// + /// This extrinsic is designed to be **unsigned** and is typically submitted + /// as an **inherent** by a block author or triggered internally by the runtime. + /// It acts as a router, taking a wrapped message and calling the dispatch logic + /// provided by the `Config::InherentHandlers` type. + #[pallet::call_index(12)] + #[pallet::weight(Weight::zero())] + pub fn system_log_dispatch( + origin: OriginFor, + message: InherentHandlerMessage, + ) -> DispatchResult { + ensure_none(origin)?; + + T::InherentHandlers::dispatch_message(message)?; + + Ok(()) + } + } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + + /// Validates unsigned `system_log_dispatch` calls before they enter the transaction pool. + /// + /// This function implements the `ValidateUnsigned` trait for `pallet-revive`. Its primary role + /// is to ensure that incoming unsigned transactions destined for `system_log_dispatch` + /// are valid before being accepted. + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { + if let Call::system_log_dispatch { message } = call { + ensure!(T::InherentHandlers::is_valid_handler(&message.handler_name), InvalidTransaction::Call); + + ValidTransaction::with_tag_prefix("SystemLogDispatch") + .and_provides(message.encode()) + .longevity(TransactionLongevity::MAX) + .propagate(true) + .build() + } else { + InvalidTransaction::Call.into() + } + } } } @@ -1459,6 +1542,8 @@ fn dispatch_result( .map_err(|e| DispatchErrorWithPostInfo { post_info, error: e }) } + + impl Pallet { /// A generalized version of [`Self::call`]. /// From ff5b002df8187abc202dd3f1083ade23580d0fd5 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Wed, 29 Oct 2025 15:08:00 +0100 Subject: [PATCH 2/4] fix up merge conflict issues --- .../frame/revive/rpc/src/receipt_extractor.rs | 200 +++++++++--------- 1 file changed, 97 insertions(+), 103 deletions(-) diff --git a/substrate/frame/revive/rpc/src/receipt_extractor.rs b/substrate/frame/revive/rpc/src/receipt_extractor.rs index bb27ef8d07a12..b76b5ea88bd76 100644 --- a/substrate/frame/revive/rpc/src/receipt_extractor.rs +++ b/substrate/frame/revive/rpc/src/receipt_extractor.rs @@ -28,7 +28,7 @@ use crate::{ use futures::{stream, StreamExt}; use pallet_revive::{ create1, - evm::{GenericTransaction, Log, ReceiptGasInfo, ReceiptInfo, TransactionSigned, H256, U256}, + evm::{Byte, GenericTransaction, Log, ReceiptGasInfo, ReceiptInfo, TransactionSigned, H256, U256}, }; use sp_core::keccak_256; use std::{future::Future, pin::Pin, sync::Arc}; @@ -167,11 +167,11 @@ impl ReceiptExtractor { } /// Extract a [`TransactionSigned`] and a [`ReceiptInfo`] from an extrinsic. - async fn extract_from_extrinsic( + async fn extract_from_eth_extrinsic( &self, substrate_block: &SubstrateBlock, eth_block_hash: H256, - ext: subxt::blocks::ExtrinsicDetails>, + ext: &ExtrinsicDetails>, call: EthTransact, receipt_gas_info: ReceiptGasInfo, transaction_index: usize, @@ -181,9 +181,9 @@ impl ReceiptExtractor { let success = events.has::().inspect_err(|err| { log::debug!( - target: LOG_TARGET, - "Failed to lookup for ExtrinsicSuccess event in block {block_number}: {err:?}" - ); + target: LOG_TARGET, + "Failed to lookup for ExtrinsicSuccess event in block {block_number}: {err:?}" + ); })?; let transaction_hash = H256(keccak_256(&call.payload)); @@ -255,14 +255,13 @@ impl ReceiptExtractor { /// Extract a [`TransactionSigned`] and a [`ReceiptInfo`] from a System Log extrinsic. async fn extract_from_system_log( &self, - block: &SubstrateBlock, - ext: &subxt::blocks::ExtrinsicDetails>, + substrate_block: &SubstrateBlock, + eth_block_hash: H256, + ext: &ExtrinsicDetails>, _call: SystemLogDispatch, + transaction_index: usize, ) -> Result<(TransactionSigned, ReceiptInfo), ClientError> { - let transaction_index = ext.index(); - let block_number = U256::from(block.number()); - let block_hash = block.hash(); - + let block_number = U256::from(substrate_block.number()); let events = ext.events().await?; let success = events.has::().inspect_err(|err| { @@ -282,28 +281,28 @@ impl ReceiptExtractor { let event_details = event_details.ok()?; let event = event_details.as_event::().ok()??; - Some( Log { + Some(Log { address: event.contract, - block_hash, - block_number, - data: Some(event.data.into()), - log_index: event_details.index().into(), topics: event.topics, + data: Some(event.data.into()), + block_number, transaction_hash, transaction_index: transaction_index.into(), + block_hash: eth_block_hash, + log_index: event_details.index().into(), ..Default::default() }) - }).collect(); + }) + .collect(); - let contract_adddress = None; + let contract_address = None; let to_address = None; - - let tx_type: pallet_revive::evm::Byte = pallet_revive::evm::Byte(0u8); + let tx_type: Byte = Byte(0u8); let receipt = ReceiptInfo::new( - block_hash, + eth_block_hash, block_number, - contract_adddress, + contract_address, from, logs, to_address, @@ -312,12 +311,9 @@ impl ReceiptExtractor { success, transaction_hash, transaction_index.into(), - tx_type + tx_type, ); - Ok((signed_tx, receipt)) - - } /// Extract receipts from block. @@ -329,7 +325,9 @@ impl ReceiptExtractor { return Ok(vec![]); } - let ext_iter = self.get_block_extrinsics(block).await?; + let extrinsics = block.extrinsics().await.inspect_err(|err| { + log::debug!(target: LOG_TARGET, "Error fetching for #{:?} extrinsics: {err:?}", block.number()); + })?; let substrate_block_number = block.number() as u64; let substrate_block_hash = block.hash(); @@ -338,72 +336,53 @@ impl ReceiptExtractor { .await .unwrap_or(substrate_block_hash); - // Process extrinsics in order while maintaining parallelism within buffer window - stream::iter(ext_iter) - .map(|(ext, call, receipt, ext_idx)| async move { - self.extract_from_extrinsic(block, eth_block_hash, ext, call, receipt, ext_idx) - .await - .inspect_err(|err| { - log::warn!(target: LOG_TARGET, "Error extracting extrinsic: {err:?}"); - }) - }) - .buffered(10) - .collect::>>() - .await - .into_iter() - .collect::, _>>() - } - - /// Return the ETH extrinsics of the block grouped with reconstruction receipt info and - /// extrinsic index - pub async fn get_block_extrinsics( - &self, - block: &SubstrateBlock, - ) -> Result< - impl Iterator< - Item = ( - ExtrinsicDetails>, - EthTransact, - ReceiptGasInfo, - usize, - ), - >, - ClientError, - > { - // Filter extrinsics from pallet_revive - let extrinsics = block.extrinsics().await.inspect_err(|err| { - log::debug!(target: LOG_TARGET, "Error fetching for #{:?} extrinsics: {err:?}", block.number()); - })?; - - let receipt_data = (self.fetch_receipt_data)(block.hash()) - .await - .ok_or(ClientError::ReceiptDataNotFound)?; - let extrinsics: Vec<_> = extrinsics - .iter() - .enumerate() - .flat_map(|(ext_idx, ext)| { - let call = ext.as_extrinsic::().ok()??; - Some((ext, call, ext_idx)) - }) - .collect(); + let receipt_data_map: Option> = (self.fetch_receipt_data)(substrate_block_hash).await; + let mut receipt_data_iter = receipt_data_map.clone().unwrap_or_default().into_iter(); + + let mut results = Vec::new(); + let mut eth_tx_count = 0; + + for (ext_idx, ext) in extrinsics.iter().enumerate() { + if let Some(call) = ext.as_extrinsic::().ok().flatten() { + let receipt_gas_info = receipt_data_iter.next().ok_or_else(|| { + log::error!( + target: LOG_TARGET, + "Receipt data missing for EthTransact at index {} in block {}", + ext_idx, substrate_block_number + ); + ClientError::ReceiptDataLengthMismatch + })?; + + match self.extract_from_eth_extrinsic(block, eth_block_hash, &ext, call, receipt_gas_info, ext_idx).await { + Ok(receipt_info) => results.push(Ok(receipt_info)), + Err(e) => { + log::warn!(target: LOG_TARGET, "Error extracting EthTransact extrinsic: {e:?}"); + } + } + eth_tx_count += 1; + } + else if let Some(call) = ext.as_extrinsic::().ok().flatten() { + match self.extract_from_system_log(block, eth_block_hash, &ext, call, ext_idx).await { + Ok(receipt_info) => results.push(Ok(receipt_info)), + Err(e) => { + log::warn!(target: LOG_TARGET, "Error extracting SystemLogDispatch extrinsic: {e:?}"); + } + } + } + } - // Sanity check we received enough data from the pallet revive. - if receipt_data.len() != extrinsics.len() { + if eth_tx_count != receipt_data_map.clone().unwrap_or_default().len() { log::error!( - target: LOG_TARGET, - "Receipt data length ({}) does not match extrinsics length ({})", - receipt_data.len(), - extrinsics.len() - ); - Err(ClientError::ReceiptDataLengthMismatch) - } else { - Ok(extrinsics - .into_iter() - .zip(receipt_data) - .map(|((extr, call, ext_idx), rec)| (extr, call, rec, ext_idx))) + target: LOG_TARGET, + "Processed {} EthTransact but found {} ReceiptGasInfo entries in block {}", + eth_tx_count, receipt_data_map.unwrap_or_default().len(), substrate_block_number + ); } + + results.into_iter().collect::, _>>() } + /// Extract a [`TransactionSigned`] and a [`ReceiptInfo`] for a specific transaction in a /// [`SubstrateBlock`] pub async fn extract_from_transaction( @@ -411,11 +390,10 @@ impl ReceiptExtractor { block: &SubstrateBlock, transaction_index: usize, ) -> Result<(TransactionSigned, ReceiptInfo), ClientError> { - let ext_iter = self.get_block_extrinsics(block).await?; - - let (ext, eth_call, receipt_gas_info, _) = ext_iter - .into_iter() - .find(|(_, _, _, ext_idx)| *ext_idx == transaction_index) + let extrinsics = block.extrinsics().await?; + let ext = extrinsics + .iter() + .nth(transaction_index) .ok_or(ClientError::EthExtrinsicNotFound)?; let substrate_block_number = block.number() as u64; @@ -425,15 +403,31 @@ impl ReceiptExtractor { .await .unwrap_or(substrate_block_hash); - self.extract_from_extrinsic( - block, - eth_block_hash, - ext, - eth_call, - receipt_gas_info, - transaction_index, - ) - .await + if let Some(call) = ext.as_extrinsic::().ok().flatten() { + let receipt_data = (self.fetch_receipt_data)(block.hash()) + .await + .ok_or(ClientError::ReceiptDataNotFound)?; + + let eth_tx_index = extrinsics.iter().take(transaction_index).filter(|e| { + e.as_extrinsic::().ok().flatten().is_some() + }).count(); + + let receipt_gas_info = receipt_data.get(eth_tx_index).cloned().ok_or_else(|| { + log::error!( + target: LOG_TARGET, + "Receipt data missing for EthTransact at index {} (eth_tx_index {}) in block {}", + transaction_index, eth_tx_index, substrate_block_number + ); + ClientError::ReceiptDataLengthMismatch + })?; + + self.extract_from_eth_extrinsic(block, eth_block_hash, &ext, call, receipt_gas_info, transaction_index).await + + } else if let Some(call) = ext.as_extrinsic::().ok().flatten() { + self.extract_from_system_log(block, eth_block_hash, &ext, call, transaction_index).await + } else { + Err(ClientError::EthExtrinsicNotFound) + } } /// Get the Ethereum block hash for the Substrate block with specific hash. From b99d3bcc6247cfce6e54e2d692756a1e441ec854 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Wed, 29 Oct 2025 15:21:18 +0100 Subject: [PATCH 3/4] merge conflict fix --- substrate/frame/revive/rpc/src/receipt_extractor.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/substrate/frame/revive/rpc/src/receipt_extractor.rs b/substrate/frame/revive/rpc/src/receipt_extractor.rs index 833847f392443..e145627294c08 100644 --- a/substrate/frame/revive/rpc/src/receipt_extractor.rs +++ b/substrate/frame/revive/rpc/src/receipt_extractor.rs @@ -266,8 +266,11 @@ impl ReceiptExtractor { let block_number = U256::from(substrate_block.number()); let events = ext.events().await?; - let success = events.has::().inspect_err(|err| { - log::debug!(target: LOG_TARGET, "Failed to lookup for ExtrinsicSuccess event in block {block_number}: {err:?}") + let success = !events.has::().inspect_err(|err| { + log::debug!( + target: LOG_TARGET, + "Failed to lookup for EthExtrinsicRevert event in block {block_number}: {err:?}" + ); })?; let transaction_hash = ext.hash(); From a756c2278712938e64bfa3f22600ea6b5592364b Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 4 Nov 2025 13:39:46 +0100 Subject: [PATCH 4/4] dispatch message --- substrate/frame/revive/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 390b10af51f67..c6610310051f5 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -57,7 +57,7 @@ use crate::{ }, exec::{AccountIdOf, ExecError, Stack as ExecStack}, gas::GasMeter, - inherent_handlers::{InherentHandler, InherentHandlers}, + inherent_handlers::InherentHandlers, storage::{meter::Meter as StorageMeter, AccountType, DeletionQueueManager}, tracing::if_tracing, vm::{pvm::extract_code_and_data, CodeInfo, RuntimeCosts}, @@ -1530,6 +1530,8 @@ pub mod pallet { if let Call::system_log_dispatch { message } = call { ensure!(T::InherentHandlers::is_valid_handler(&message.handler_name), InvalidTransaction::Call); + T::InherentHandlers::dispatch_message(message.clone()).map_err(|_| InvalidTransaction::BadProof)?; + ValidTransaction::with_tag_prefix("SystemLogDispatch") .and_provides(message.encode()) .longevity(TransactionLongevity::MAX)