Skip to content

Commit 90d008d

Browse files
authored
feat: add methods to execution outcome (#65)
* feat: add methods to execution outcome * chore: version
1 parent 0fce745 commit 90d008d

File tree

6 files changed

+106
-11
lines changed

6 files changed

+106
-11
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ members = ["crates/*"]
33
resolver = "2"
44

55
[workspace.package]
6-
version = "0.2.1"
6+
version = "0.2.2"
77
edition = "2021"
88
rust-version = "1.81"
99
authors = ["init4"]

crates/evm/src/outcome.rs

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
use alloy::consensus::ReceiptEnvelope;
1+
use alloy::{
2+
consensus::{ReceiptEnvelope, TxReceipt},
3+
primitives::BlockNumber,
4+
};
25
use trevm::revm::database::BundleState;
36

47
/// The outcome of a block execution, containing the bundle state,
58
/// receipts, and the first block number in the execution.
69
#[derive(Debug, Clone, PartialEq, Eq)]
710
pub struct ExecutionOutcome<T = ReceiptEnvelope> {
811
/// The bundle state after execution.
9-
pub bundle: BundleState,
12+
bundle: BundleState,
1013
/// The receipts generated during execution, grouped by block.
11-
pub receipts: Vec<Vec<T>>,
14+
receipts: Vec<Vec<T>>,
1215
/// The first block number in the execution.
13-
pub first_block: u64,
16+
first_block: u64,
1417
}
1518

1619
impl<T> Default for ExecutionOutcome<T> {
@@ -25,9 +28,99 @@ impl<T> ExecutionOutcome<T> {
2528
Self { bundle, receipts, first_block }
2629
}
2730

31+
/// Decompose the execution outcome into its parts.
32+
pub fn into_parts(self) -> (BundleState, Vec<Vec<T>>, u64) {
33+
(self.bundle, self.receipts, self.first_block)
34+
}
35+
2836
/// Append another execution outcome to this one.
2937
pub fn append(&mut self, other: Self) {
3038
self.bundle.extend(other.bundle);
3139
self.receipts.extend(other.receipts);
3240
}
41+
42+
/// Number of blocks in the execution outcome.
43+
pub fn len(&self) -> usize {
44+
self.receipts.len()
45+
}
46+
47+
/// Check if the execution outcome is empty.
48+
pub fn is_empty(&self) -> bool {
49+
self.receipts.is_empty()
50+
}
51+
52+
/// Return first block of the execution outcome
53+
pub const fn first_block(&self) -> BlockNumber {
54+
self.first_block
55+
}
56+
57+
/// Return last block of the execution outcome
58+
pub fn last_block(&self) -> BlockNumber {
59+
(self.first_block + self.len() as u64).saturating_sub(1)
60+
}
61+
62+
/// Get the bundle state.
63+
pub const fn bundle(&self) -> &BundleState {
64+
&self.bundle
65+
}
66+
67+
/// Get the receipts.
68+
pub fn receipts(&self) -> &[Vec<T>] {
69+
&self.receipts
70+
}
71+
72+
/// Get the receipts for a specific block number. Will return an empty
73+
/// slice if the block number is out of range.
74+
pub fn receipts_by_block(&self, block_number: BlockNumber) -> &[T] {
75+
self.receipts
76+
.get((block_number - self.first_block) as usize)
77+
.map(Vec::as_slice)
78+
.unwrap_or(&[])
79+
}
80+
81+
/// Extend one state from another
82+
///
83+
/// For state this is very sensitive operation and should be used only when
84+
/// we know that other state was build on top of this one.
85+
pub fn extend(&mut self, other: Self) {
86+
self.bundle.extend(other.bundle);
87+
self.receipts.extend(other.receipts);
88+
}
89+
}
90+
impl<T: TxReceipt> ExecutionOutcome<T> {
91+
/// Get an iterator over the logs
92+
pub fn logs(&self) -> impl Iterator<Item = &T::Log> {
93+
self.receipts.iter().flat_map(|r| r.iter()).flat_map(|receipt| receipt.logs())
94+
}
95+
96+
/// Get an iterator over the logs for a specific block number.
97+
pub fn logs_by_block(&self, block_number: BlockNumber) -> impl Iterator<Item = &T::Log> {
98+
self.receipts_by_block(block_number).iter().flat_map(|receipt| receipt.logs())
99+
}
33100
}
101+
102+
// Some code in this file has been copied and modified from reth
103+
// <https://github.com/paradigmxyz/reth>
104+
// The original license is included below:
105+
//
106+
// The MIT License (MIT)
107+
//
108+
// Copyright (c) 2022-2024 Reth Contributors
109+
//
110+
// Permission is hereby granted, free of charge, to any person obtaining a copy
111+
// of this software and associated documentation files (the "Software"), to deal
112+
// in the Software without restriction, including without limitation the rights
113+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
114+
// copies of the Software, and to permit persons to whom the Software is
115+
// furnished to do so, subject to the following conditions:
116+
//.
117+
// The above copyright notice and this permission notice shall be included in
118+
// all copies or substantial portions of the Software.
119+
//
120+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
121+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
122+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
123+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
124+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
125+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
126+
// THE SOFTWARE.

crates/evm/src/result.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl<T, H> BlockResult<T, H> {
4141
HostJournal::new(
4242
host_block,
4343
prev_journal_hash,
44-
BundleStateIndex::from(&self.execution_outcome.bundle),
44+
BundleStateIndex::from(self.execution_outcome.bundle()),
4545
)
4646
}
4747
}

crates/test-utils/src/chain.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl Extractable for Chain {
4747
type Receipt = ReceiptEnvelope;
4848

4949
fn blocks_and_receipts(&self) -> impl Iterator<Item = (&Self::Block, &Vec<Self::Receipt>)> {
50-
self.blocks.iter().zip(self.execution_outcome.receipts.iter())
50+
self.blocks.iter().zip(self.execution_outcome.receipts().iter())
5151
}
5252
}
5353

crates/test-utils/src/convert.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,12 @@ impl ToRethPrimitive for ExecutionOutcome {
8787
type RethPrimitive = reth::providers::ExecutionOutcome;
8888

8989
fn to_reth(self) -> Self::RethPrimitive {
90+
let (bundle, receipts, first_block) = self.into_parts();
91+
9092
reth::providers::ExecutionOutcome {
91-
bundle: self.bundle,
92-
receipts: self.receipts.into_iter().map(ToRethPrimitive::to_reth).collect(),
93-
first_block: self.first_block,
93+
bundle,
94+
receipts: receipts.into_iter().map(ToRethPrimitive::to_reth).collect(),
95+
first_block,
9496
requests: vec![],
9597
}
9698
}

crates/test-utils/src/specs/host_spec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ impl HostBlockSpec {
348348
receipts.first_mut().unwrap().push(receipt);
349349
}
350350

351-
ExecutionOutcome { bundle: Default::default(), receipts, first_block: self.block_number() }
351+
ExecutionOutcome::new(Default::default(), receipts, self.block_number())
352352
}
353353

354354
/// Make a chain

0 commit comments

Comments
 (0)