Skip to content

Commit

Permalink
chore(util): Add reth payload util (#12590)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDhejavu authored Nov 16, 2024
1 parent 02237bf commit 5276093
Show file tree
Hide file tree
Showing 14 changed files with 207 additions and 152 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ members = [
"crates/payload/builder/",
"crates/payload/primitives/",
"crates/payload/validator/",
"crates/payload/util/",
"crates/primitives-traits/",
"crates/primitives/",
"crates/prune/prune",
Expand Down Expand Up @@ -381,6 +382,7 @@ reth-optimism-storage = { path = "crates/optimism/storage" }
reth-payload-builder = { path = "crates/payload/builder" }
reth-payload-primitives = { path = "crates/payload/primitives" }
reth-payload-validator = { path = "crates/payload/validator" }
reth-payload-util = { path = "crates/payload/util" }
reth-primitives = { path = "crates/primitives", default-features = false, features = [
"std",
] }
Expand Down
1 change: 1 addition & 0 deletions crates/optimism/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ reth-chainspec.workspace = true
reth-engine-local.workspace = true
reth-primitives.workspace = true
reth-payload-builder.workspace = true
reth-payload-util.workspace = true
reth-basic-payload-builder.workspace = true
reth-consensus.workspace = true
reth-node-api.workspace = true
Expand Down
6 changes: 2 additions & 4 deletions crates/optimism/node/tests/it/priority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ use reth_optimism_node::{
OpEngineTypes, OpNode,
};
use reth_optimism_payload_builder::builder::OpPayloadTransactions;
use reth_payload_util::{PayloadTransactions, PayloadTransactionsChain, PayloadTransactionsFixed};
use reth_primitives::{SealedBlock, Transaction, TransactionSigned, TransactionSignedEcRecovered};
use reth_provider::providers::BlockchainProvider2;
use reth_transaction_pool::{
pool::{BestPayloadTransactions, PayloadTransactionsChain, PayloadTransactionsFixed},
PayloadTransactions,
};
use reth_transaction_pool::pool::BestPayloadTransactions;
use std::sync::Arc;
use tokio::sync::Mutex;

Expand Down
1 change: 1 addition & 0 deletions crates/optimism/payload/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ reth-rpc-types-compat.workspace = true
reth-evm.workspace = true
reth-execution-types.workspace = true
reth-payload-builder.workspace = true
reth-payload-util.workspace = true
reth-payload-primitives = { workspace = true, features = ["op"] }
reth-basic-payload-builder.workspace = true
reth-trie.workspace = true
Expand Down
3 changes: 2 additions & 1 deletion crates/optimism/payload/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use reth_optimism_chainspec::OpChainSpec;
use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism;
use reth_optimism_forks::OpHardforks;
use reth_payload_primitives::{PayloadBuilderAttributes, PayloadBuilderError};
use reth_payload_util::PayloadTransactions;
use reth_primitives::{
proofs,
revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg},
Expand All @@ -24,7 +25,7 @@ use reth_primitives::{
use reth_provider::{ProviderError, StateProofProvider, StateProviderFactory, StateRootProvider};
use reth_revm::database::StateProviderDatabase;
use reth_transaction_pool::{
noop::NoopTransactionPool, BestTransactionsAttributes, PayloadTransactions, TransactionPool,
noop::NoopTransactionPool, BestTransactionsAttributes, TransactionPool,
};
use reth_trie::HashedPostState;
use revm::{
Expand Down
20 changes: 20 additions & 0 deletions crates/payload/util/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "reth-payload-util"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
description = "reth payload utilities"

[lints]
workspace = true

[dependencies]
# reth
reth-primitives.workspace = true

# alloy
alloy-primitives.workspace = true
alloy-consensus.workspace = true
15 changes: 15 additions & 0 deletions crates/payload/util/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//! payload utils.

#![doc(
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

mod traits;
mod transaction;

pub use traits::PayloadTransactions;
pub use transaction::{PayloadTransactionsChain, PayloadTransactionsFixed};
20 changes: 20 additions & 0 deletions crates/payload/util/src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use alloy_primitives::Address;
use reth_primitives::TransactionSignedEcRecovered;

/// Iterator that returns transactions for the block building process in the order they should be
/// included in the block.
///
/// Can include transactions from the pool and other sources (alternative pools,
/// sequencer-originated transactions, etc.).
pub trait PayloadTransactions {
/// Returns the next transaction to include in the block.
fn next(
&mut self,
// In the future, `ctx` can include access to state for block building purposes.
ctx: (),
) -> Option<TransactionSignedEcRecovered>;

/// Exclude descendants of the transaction with given sender and nonce from the iterator,
/// because this transaction won't be included in the block.
fn mark_invalid(&mut self, sender: Address, nonce: u64);
}
128 changes: 128 additions & 0 deletions crates/payload/util/src/transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use crate::PayloadTransactions;
use alloy_consensus::Transaction;
use alloy_primitives::Address;
use reth_primitives::TransactionSignedEcRecovered;

/// An implementation of [`crate::traits::PayloadTransactions`] that yields
/// a pre-defined set of transactions.
///
/// This is useful to put a sequencer-specified set of transactions into the block
/// and compose it with the rest of the transactions.
#[derive(Debug)]
pub struct PayloadTransactionsFixed<T> {
transactions: Vec<T>,
index: usize,
}

impl<T> PayloadTransactionsFixed<T> {
/// Constructs a new [`PayloadTransactionsFixed`].
pub fn new(transactions: Vec<T>) -> Self {
Self { transactions, index: Default::default() }
}

/// Constructs a new [`PayloadTransactionsFixed`] with a single transaction.
pub fn single(transaction: T) -> Self {
Self { transactions: vec![transaction], index: Default::default() }
}
}

impl PayloadTransactions for PayloadTransactionsFixed<TransactionSignedEcRecovered> {
fn next(&mut self, _ctx: ()) -> Option<TransactionSignedEcRecovered> {
(self.index < self.transactions.len()).then(|| {
let tx = self.transactions[self.index].clone();
self.index += 1;
tx
})
}

fn mark_invalid(&mut self, _sender: Address, _nonce: u64) {}
}

/// Wrapper over [`crate::traits::PayloadTransactions`] that combines transactions from multiple
/// `PayloadTransactions` iterators and keeps track of the gas for both of iterators.
///
/// We can't use [`Iterator::chain`], because:
/// (a) we need to propagate the `mark_invalid` and `no_updates`
/// (b) we need to keep track of the gas
///
/// Notes that [`PayloadTransactionsChain`] fully drains the first iterator
/// before moving to the second one.
///
/// If the `before` iterator has transactions that are not fitting into the block,
/// the after iterator will get propagated a `mark_invalid` call for each of them.
#[derive(Debug)]
pub struct PayloadTransactionsChain<B: PayloadTransactions, A: PayloadTransactions> {
/// Iterator that will be used first
before: B,
/// Allowed gas for the transactions from `before` iterator. If `None`, no gas limit is
/// enforced.
before_max_gas: Option<u64>,
/// Gas used by the transactions from `before` iterator
before_gas: u64,
/// Iterator that will be used after `before` iterator
after: A,
/// Allowed gas for the transactions from `after` iterator. If `None`, no gas limit is
/// enforced.
after_max_gas: Option<u64>,
/// Gas used by the transactions from `after` iterator
after_gas: u64,
}

impl<B: PayloadTransactions, A: PayloadTransactions> PayloadTransactionsChain<B, A> {
/// Constructs a new [`PayloadTransactionsChain`].
pub fn new(
before: B,
before_max_gas: Option<u64>,
after: A,
after_max_gas: Option<u64>,
) -> Self {
Self {
before,
before_max_gas,
before_gas: Default::default(),
after,
after_max_gas,
after_gas: Default::default(),
}
}
}

impl<B, A> PayloadTransactions for PayloadTransactionsChain<B, A>
where
B: PayloadTransactions,
A: PayloadTransactions,
{
fn next(&mut self, ctx: ()) -> Option<TransactionSignedEcRecovered> {
while let Some(tx) = self.before.next(ctx) {
if let Some(before_max_gas) = self.before_max_gas {
if self.before_gas + tx.transaction.gas_limit() <= before_max_gas {
self.before_gas += tx.transaction.gas_limit();
return Some(tx);
}
self.before.mark_invalid(tx.signer(), tx.transaction.nonce());
self.after.mark_invalid(tx.signer(), tx.transaction.nonce());
} else {
return Some(tx);
}
}

while let Some(tx) = self.after.next(ctx) {
if let Some(after_max_gas) = self.after_max_gas {
if self.after_gas + tx.transaction.gas_limit() <= after_max_gas {
self.after_gas += tx.transaction.gas_limit();
return Some(tx);
}
self.after.mark_invalid(tx.signer(), tx.transaction.nonce());
} else {
return Some(tx);
}
}

None
}

fn mark_invalid(&mut self, sender: Address, nonce: u64) {
self.before.mark_invalid(sender, nonce);
self.after.mark_invalid(sender, nonce);
}
}
1 change: 1 addition & 0 deletions crates/transaction-pool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ reth-chainspec.workspace = true
reth-eth-wire-types.workspace = true
reth-primitives = { workspace = true, features = ["c-kzg", "secp256k1"] }
reth-primitives-traits.workspace = true
reth-payload-util.workspace = true
reth-execution-types.workspace = true
reth-fs-util.workspace = true
reth-storage-api.workspace = true
Expand Down
Loading

0 comments on commit 5276093

Please sign in to comment.