diff --git a/Cargo.toml b/Cargo.toml index 112a7545..ef59cc01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.2.1" +version = "0.2.2" edition = "2021" rust-version = "1.81" authors = ["init4"] diff --git a/crates/evm/src/outcome.rs b/crates/evm/src/outcome.rs index d350e531..47380138 100644 --- a/crates/evm/src/outcome.rs +++ b/crates/evm/src/outcome.rs @@ -1,4 +1,7 @@ -use alloy::consensus::ReceiptEnvelope; +use alloy::{ + consensus::{ReceiptEnvelope, TxReceipt}, + primitives::BlockNumber, +}; use trevm::revm::database::BundleState; /// The outcome of a block execution, containing the bundle state, @@ -6,11 +9,11 @@ use trevm::revm::database::BundleState; #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExecutionOutcome { /// The bundle state after execution. - pub bundle: BundleState, + bundle: BundleState, /// The receipts generated during execution, grouped by block. - pub receipts: Vec>, + receipts: Vec>, /// The first block number in the execution. - pub first_block: u64, + first_block: u64, } impl Default for ExecutionOutcome { @@ -25,9 +28,99 @@ impl ExecutionOutcome { Self { bundle, receipts, first_block } } + /// Decompose the execution outcome into its parts. + pub fn into_parts(self) -> (BundleState, Vec>, u64) { + (self.bundle, self.receipts, self.first_block) + } + /// Append another execution outcome to this one. pub fn append(&mut self, other: Self) { self.bundle.extend(other.bundle); self.receipts.extend(other.receipts); } + + /// Number of blocks in the execution outcome. + pub fn len(&self) -> usize { + self.receipts.len() + } + + /// Check if the execution outcome is empty. + pub fn is_empty(&self) -> bool { + self.receipts.is_empty() + } + + /// Return first block of the execution outcome + pub const fn first_block(&self) -> BlockNumber { + self.first_block + } + + /// Return last block of the execution outcome + pub fn last_block(&self) -> BlockNumber { + (self.first_block + self.len() as u64).saturating_sub(1) + } + + /// Get the bundle state. + pub const fn bundle(&self) -> &BundleState { + &self.bundle + } + + /// Get the receipts. + pub fn receipts(&self) -> &[Vec] { + &self.receipts + } + + /// Get the receipts for a specific block number. Will return an empty + /// slice if the block number is out of range. + pub fn receipts_by_block(&self, block_number: BlockNumber) -> &[T] { + self.receipts + .get((block_number - self.first_block) as usize) + .map(Vec::as_slice) + .unwrap_or(&[]) + } + + /// Extend one state from another + /// + /// For state this is very sensitive operation and should be used only when + /// we know that other state was build on top of this one. + pub fn extend(&mut self, other: Self) { + self.bundle.extend(other.bundle); + self.receipts.extend(other.receipts); + } +} +impl ExecutionOutcome { + /// Get an iterator over the logs + pub fn logs(&self) -> impl Iterator { + self.receipts.iter().flat_map(|r| r.iter()).flat_map(|receipt| receipt.logs()) + } + + /// Get an iterator over the logs for a specific block number. + pub fn logs_by_block(&self, block_number: BlockNumber) -> impl Iterator { + self.receipts_by_block(block_number).iter().flat_map(|receipt| receipt.logs()) + } } + +// Some code in this file has been copied and modified from reth +// +// The original license is included below: +// +// The MIT License (MIT) +// +// Copyright (c) 2022-2024 Reth Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +//. +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. diff --git a/crates/evm/src/result.rs b/crates/evm/src/result.rs index 4ebdd2bd..5532aef2 100644 --- a/crates/evm/src/result.rs +++ b/crates/evm/src/result.rs @@ -41,7 +41,7 @@ impl BlockResult { HostJournal::new( host_block, prev_journal_hash, - BundleStateIndex::from(&self.execution_outcome.bundle), + BundleStateIndex::from(self.execution_outcome.bundle()), ) } } diff --git a/crates/test-utils/src/chain.rs b/crates/test-utils/src/chain.rs index 25faf305..5838a245 100644 --- a/crates/test-utils/src/chain.rs +++ b/crates/test-utils/src/chain.rs @@ -47,7 +47,7 @@ impl Extractable for Chain { type Receipt = ReceiptEnvelope; fn blocks_and_receipts(&self) -> impl Iterator)> { - self.blocks.iter().zip(self.execution_outcome.receipts.iter()) + self.blocks.iter().zip(self.execution_outcome.receipts().iter()) } } diff --git a/crates/test-utils/src/convert.rs b/crates/test-utils/src/convert.rs index c59f6b45..abfa6a0c 100644 --- a/crates/test-utils/src/convert.rs +++ b/crates/test-utils/src/convert.rs @@ -87,10 +87,12 @@ impl ToRethPrimitive for ExecutionOutcome { type RethPrimitive = reth::providers::ExecutionOutcome; fn to_reth(self) -> Self::RethPrimitive { + let (bundle, receipts, first_block) = self.into_parts(); + reth::providers::ExecutionOutcome { - bundle: self.bundle, - receipts: self.receipts.into_iter().map(ToRethPrimitive::to_reth).collect(), - first_block: self.first_block, + bundle, + receipts: receipts.into_iter().map(ToRethPrimitive::to_reth).collect(), + first_block, requests: vec![], } } diff --git a/crates/test-utils/src/specs/host_spec.rs b/crates/test-utils/src/specs/host_spec.rs index ebfc14aa..4b27ad42 100644 --- a/crates/test-utils/src/specs/host_spec.rs +++ b/crates/test-utils/src/specs/host_spec.rs @@ -348,7 +348,7 @@ impl HostBlockSpec { receipts.first_mut().unwrap().push(receipt); } - ExecutionOutcome { bundle: Default::default(), receipts, first_block: self.block_number() } + ExecutionOutcome::new(Default::default(), receipts, self.block_number()) } /// Make a chain