mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: introduce OpPooledTransaction (#13548)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -8508,6 +8508,7 @@ dependencies = [
|
|||||||
"alloy-rpc-types-engine",
|
"alloy-rpc-types-engine",
|
||||||
"alloy-signer-local",
|
"alloy-signer-local",
|
||||||
"clap",
|
"clap",
|
||||||
|
"derive_more",
|
||||||
"eyre",
|
"eyre",
|
||||||
"futures",
|
"futures",
|
||||||
"op-alloy-consensus",
|
"op-alloy-consensus",
|
||||||
|
|||||||
@ -51,12 +51,14 @@ revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] }
|
|||||||
# ethereum
|
# ethereum
|
||||||
alloy-eips.workspace = true
|
alloy-eips.workspace = true
|
||||||
alloy-primitives.workspace = true
|
alloy-primitives.workspace = true
|
||||||
|
op-alloy-consensus.workspace = true
|
||||||
op-alloy-rpc-types-engine.workspace = true
|
op-alloy-rpc-types-engine.workspace = true
|
||||||
alloy-rpc-types-engine.workspace = true
|
alloy-rpc-types-engine.workspace = true
|
||||||
alloy-consensus.workspace = true
|
alloy-consensus.workspace = true
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
|
derive_more.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
eyre.workspace = true
|
eyre.workspace = true
|
||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
|
|||||||
@ -1,18 +1,28 @@
|
|||||||
//! OP transaction pool types
|
//! OP transaction pool types
|
||||||
use alloy_consensus::{BlockHeader, Transaction};
|
use alloy_consensus::{
|
||||||
|
BlobTransactionSidecar, BlobTransactionValidationError, BlockHeader, Transaction, Typed2718,
|
||||||
|
};
|
||||||
use alloy_eips::eip2718::Encodable2718;
|
use alloy_eips::eip2718::Encodable2718;
|
||||||
|
use alloy_primitives::{Address, TxHash, TxKind, U256};
|
||||||
|
use op_alloy_consensus::OpTypedTransaction;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use reth_chainspec::ChainSpec;
|
use reth_chainspec::ChainSpec;
|
||||||
use reth_node_api::{Block, BlockBody};
|
use reth_node_api::{Block, BlockBody};
|
||||||
use reth_optimism_evm::RethL1BlockInfo;
|
use reth_optimism_evm::RethL1BlockInfo;
|
||||||
use reth_primitives::{GotExpected, InvalidTransactionError, SealedBlock, TransactionSigned};
|
use reth_optimism_primitives::OpTransactionSigned;
|
||||||
|
use reth_primitives::{
|
||||||
|
transaction::TransactionConversionError, GotExpected, InvalidTransactionError, RecoveredTx,
|
||||||
|
SealedBlock, TransactionSigned,
|
||||||
|
};
|
||||||
|
use reth_primitives_traits::SignedTransaction;
|
||||||
use reth_provider::{BlockReaderIdExt, StateProviderFactory};
|
use reth_provider::{BlockReaderIdExt, StateProviderFactory};
|
||||||
use reth_revm::L1BlockInfo;
|
use reth_revm::L1BlockInfo;
|
||||||
use reth_transaction_pool::{
|
use reth_transaction_pool::{
|
||||||
CoinbaseTipOrdering, EthPoolTransaction, EthPooledTransaction, EthTransactionValidator, Pool,
|
CoinbaseTipOrdering, EthBlobTransactionSidecar, EthPoolTransaction, EthPooledTransaction,
|
||||||
TransactionOrigin, TransactionValidationOutcome, TransactionValidationTaskExecutor,
|
EthTransactionValidator, Pool, PoolTransaction, TransactionOrigin,
|
||||||
TransactionValidator,
|
TransactionValidationOutcome, TransactionValidationTaskExecutor, TransactionValidator,
|
||||||
};
|
};
|
||||||
|
use revm::primitives::{AccessList, KzgSettings};
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
atomic::{AtomicU64, Ordering},
|
atomic::{AtomicU64, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
@ -25,6 +35,167 @@ pub type OpTransactionPool<Client, S> = Pool<
|
|||||||
S,
|
S,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
/// Pool transaction for OP.
|
||||||
|
#[derive(Debug, Clone, derive_more::Deref)]
|
||||||
|
pub struct OpPooledTransaction(EthPooledTransaction<OpTransactionSigned>);
|
||||||
|
|
||||||
|
impl From<RecoveredTx<op_alloy_consensus::OpPooledTransaction>> for OpPooledTransaction {
|
||||||
|
fn from(tx: RecoveredTx<op_alloy_consensus::OpPooledTransaction>) -> Self {
|
||||||
|
let encoded_len = tx.encode_2718_len();
|
||||||
|
let tx = tx.map_transaction(|tx| tx.into());
|
||||||
|
Self(EthPooledTransaction::new(tx, encoded_len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<RecoveredTx<OpTransactionSigned>> for OpPooledTransaction {
|
||||||
|
type Error = TransactionConversionError;
|
||||||
|
|
||||||
|
fn try_from(value: RecoveredTx<OpTransactionSigned>) -> Result<Self, Self::Error> {
|
||||||
|
let (tx, signer) = value.to_components();
|
||||||
|
let pooled: RecoveredTx<op_alloy_consensus::OpPooledTransaction> =
|
||||||
|
RecoveredTx::from_signed_transaction(tx.try_into()?, signer);
|
||||||
|
Ok(pooled.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<OpPooledTransaction> for RecoveredTx<OpTransactionSigned> {
|
||||||
|
fn from(value: OpPooledTransaction) -> Self {
|
||||||
|
value.0.transaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PoolTransaction for OpPooledTransaction {
|
||||||
|
type TryFromConsensusError = <Self as TryFrom<RecoveredTx<Self::Consensus>>>::Error;
|
||||||
|
type Consensus = OpTransactionSigned;
|
||||||
|
type Pooled = op_alloy_consensus::OpPooledTransaction;
|
||||||
|
|
||||||
|
fn clone_into_consensus(&self) -> RecoveredTx<Self::Consensus> {
|
||||||
|
self.transaction().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_consensus_into_pooled(
|
||||||
|
tx: RecoveredTx<Self::Consensus>,
|
||||||
|
) -> Result<RecoveredTx<Self::Pooled>, Self::TryFromConsensusError> {
|
||||||
|
let (tx, signer) = tx.to_components();
|
||||||
|
Ok(RecoveredTx::from_signed_transaction(tx.try_into()?, signer))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash(&self) -> &TxHash {
|
||||||
|
self.transaction.tx_hash()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sender(&self) -> Address {
|
||||||
|
self.transaction.signer()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sender_ref(&self) -> &Address {
|
||||||
|
self.transaction.signer_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nonce(&self) -> u64 {
|
||||||
|
self.transaction.nonce()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cost(&self) -> &U256 {
|
||||||
|
&self.cost
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gas_limit(&self) -> u64 {
|
||||||
|
self.transaction.gas_limit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_fee_per_gas(&self) -> u128 {
|
||||||
|
self.transaction.transaction.max_fee_per_gas()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn access_list(&self) -> Option<&AccessList> {
|
||||||
|
self.transaction.access_list()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_priority_fee_per_gas(&self) -> Option<u128> {
|
||||||
|
self.transaction.transaction.max_priority_fee_per_gas()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_fee_per_blob_gas(&self) -> Option<u128> {
|
||||||
|
self.transaction.max_fee_per_blob_gas()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn effective_tip_per_gas(&self, base_fee: u64) -> Option<u128> {
|
||||||
|
self.transaction.effective_tip_per_gas(base_fee)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn priority_fee_or_price(&self) -> u128 {
|
||||||
|
self.transaction.priority_fee_or_price()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kind(&self) -> TxKind {
|
||||||
|
self.transaction.kind()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_create(&self) -> bool {
|
||||||
|
self.transaction.is_create()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input(&self) -> &[u8] {
|
||||||
|
self.transaction.input()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
self.transaction.transaction.input().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tx_type(&self) -> u8 {
|
||||||
|
self.transaction.ty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encoded_length(&self) -> usize {
|
||||||
|
self.encoded_length
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chain_id(&self) -> Option<u64> {
|
||||||
|
self.transaction.chain_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EthPoolTransaction for OpPooledTransaction {
|
||||||
|
fn take_blob(&mut self) -> EthBlobTransactionSidecar {
|
||||||
|
EthBlobTransactionSidecar::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blob_count(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_into_pooled_eip4844(
|
||||||
|
self,
|
||||||
|
_sidecar: Arc<BlobTransactionSidecar>,
|
||||||
|
) -> Option<RecoveredTx<Self::Pooled>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_from_eip4844(
|
||||||
|
_tx: RecoveredTx<Self::Consensus>,
|
||||||
|
_sidecar: BlobTransactionSidecar,
|
||||||
|
) -> Option<Self> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_blob(
|
||||||
|
&self,
|
||||||
|
_sidecar: &BlobTransactionSidecar,
|
||||||
|
_settings: &KzgSettings,
|
||||||
|
) -> Result<(), BlobTransactionValidationError> {
|
||||||
|
Err(BlobTransactionValidationError::NotBlobTransaction(self.tx_type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn authorization_count(&self) -> usize {
|
||||||
|
match &self.transaction.transaction {
|
||||||
|
OpTypedTransaction::Eip7702(tx) => tx.authorization_list.len(),
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Validator for Optimism transactions.
|
/// Validator for Optimism transactions.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct OpTransactionValidator<Client, Tx> {
|
pub struct OpTransactionValidator<Client, Tx> {
|
||||||
|
|||||||
@ -1192,20 +1192,20 @@ pub trait EthPoolTransaction: PoolTransaction {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct EthPooledTransaction<T = TransactionSigned> {
|
pub struct EthPooledTransaction<T = TransactionSigned> {
|
||||||
/// `EcRecovered` transaction, the consensus format.
|
/// `EcRecovered` transaction, the consensus format.
|
||||||
pub(crate) transaction: RecoveredTx<T>,
|
pub transaction: RecoveredTx<T>,
|
||||||
|
|
||||||
/// For EIP-1559 transactions: `max_fee_per_gas * gas_limit + tx_value`.
|
/// For EIP-1559 transactions: `max_fee_per_gas * gas_limit + tx_value`.
|
||||||
/// For legacy transactions: `gas_price * gas_limit + tx_value`.
|
/// For legacy transactions: `gas_price * gas_limit + tx_value`.
|
||||||
/// For EIP-4844 blob transactions: `max_fee_per_gas * gas_limit + tx_value +
|
/// For EIP-4844 blob transactions: `max_fee_per_gas * gas_limit + tx_value +
|
||||||
/// max_blob_fee_per_gas * blob_gas_used`.
|
/// max_blob_fee_per_gas * blob_gas_used`.
|
||||||
pub(crate) cost: U256,
|
pub cost: U256,
|
||||||
|
|
||||||
/// This is the RLP length of the transaction, computed when the transaction is added to the
|
/// This is the RLP length of the transaction, computed when the transaction is added to the
|
||||||
/// pool.
|
/// pool.
|
||||||
pub(crate) encoded_length: usize,
|
pub encoded_length: usize,
|
||||||
|
|
||||||
/// The blob side car for this transaction
|
/// The blob side car for this transaction
|
||||||
pub(crate) blob_sidecar: EthBlobTransactionSidecar,
|
pub blob_sidecar: EthBlobTransactionSidecar,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: SignedTransaction> EthPooledTransaction<T> {
|
impl<T: SignedTransaction> EthPooledTransaction<T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user