mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-09 23:38:10 -05:00
refactor(rpc-convert): move rpc conversion traits/impls to alloy-evm (#19616)
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -10243,6 +10243,7 @@ name = "reth-rpc-convert"
|
||||
version = "1.9.2"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-evm",
|
||||
"alloy-json-rpc",
|
||||
"alloy-network",
|
||||
"alloy-primitives",
|
||||
@@ -10254,13 +10255,11 @@ dependencies = [
|
||||
"op-alloy-consensus",
|
||||
"op-alloy-network",
|
||||
"op-alloy-rpc-types",
|
||||
"op-revm",
|
||||
"reth-ethereum-primitives",
|
||||
"reth-evm",
|
||||
"reth-optimism-primitives",
|
||||
"reth-primitives-traits",
|
||||
"reth-storage-api",
|
||||
"revm-context",
|
||||
"serde_json",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
@@ -80,4 +80,4 @@ portable = [
|
||||
"op-revm/portable",
|
||||
"revm/portable",
|
||||
]
|
||||
rpc = ["reth-rpc-eth-api", "reth-optimism-primitives/serde", "reth-optimism-primitives/reth-codec"]
|
||||
rpc = ["reth-rpc-eth-api", "reth-optimism-primitives/serde", "reth-optimism-primitives/reth-codec", "alloy-evm/rpc"]
|
||||
|
||||
@@ -25,16 +25,13 @@ alloy-signer.workspace = true
|
||||
alloy-consensus.workspace = true
|
||||
alloy-network.workspace = true
|
||||
alloy-json-rpc.workspace = true
|
||||
alloy-evm = { workspace = true, features = ["rpc"] }
|
||||
|
||||
# optimism
|
||||
op-alloy-consensus = { workspace = true, optional = true }
|
||||
op-alloy-rpc-types = { workspace = true, optional = true }
|
||||
op-alloy-network = { workspace = true, optional = true }
|
||||
reth-optimism-primitives = { workspace = true, optional = true }
|
||||
op-revm = { workspace = true, optional = true }
|
||||
|
||||
# revm
|
||||
revm-context.workspace = true
|
||||
|
||||
# io
|
||||
jsonrpsee-types.workspace = true
|
||||
@@ -56,7 +53,7 @@ op = [
|
||||
"dep:op-alloy-network",
|
||||
"dep:reth-optimism-primitives",
|
||||
"dep:reth-storage-api",
|
||||
"dep:op-revm",
|
||||
"reth-evm/op",
|
||||
"reth-primitives-traits/op",
|
||||
"alloy-evm/op",
|
||||
]
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
use alloy_primitives::{B256, U256};
|
||||
use std::cmp::min;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Helper type for representing the fees of a `TransactionRequest`
|
||||
#[derive(Debug)]
|
||||
pub struct CallFees {
|
||||
/// EIP-1559 priority fee
|
||||
pub max_priority_fee_per_gas: Option<U256>,
|
||||
/// Unified gas price setting
|
||||
///
|
||||
/// Will be the configured `basefee` if unset in the request
|
||||
///
|
||||
/// `gasPrice` for legacy,
|
||||
/// `maxFeePerGas` for EIP-1559
|
||||
pub gas_price: U256,
|
||||
/// Max Fee per Blob gas for EIP-4844 transactions
|
||||
pub max_fee_per_blob_gas: Option<U256>,
|
||||
}
|
||||
|
||||
impl CallFees {
|
||||
/// Ensures the fields of a `TransactionRequest` are not conflicting.
|
||||
///
|
||||
/// # EIP-4844 transactions
|
||||
///
|
||||
/// Blob transactions have an additional fee parameter `maxFeePerBlobGas`.
|
||||
/// If the `maxFeePerBlobGas` or `blobVersionedHashes` are set we treat it as an EIP-4844
|
||||
/// transaction.
|
||||
///
|
||||
/// Note: Due to the `Default` impl of [`BlockEnv`] (Some(0)) this assumes the `block_blob_fee`
|
||||
/// is always `Some`
|
||||
///
|
||||
/// ## Notable design decisions
|
||||
///
|
||||
/// For compatibility reasons, this contains several exceptions when fee values are validated:
|
||||
/// - If both `maxFeePerGas` and `maxPriorityFeePerGas` are set to `0` they are treated as
|
||||
/// missing values, bypassing fee checks wrt. `baseFeePerGas`.
|
||||
///
|
||||
/// This mirrors geth's behaviour when transaction requests are executed: <https://github.com/ethereum/go-ethereum/blob/380688c636a654becc8f114438c2a5d93d2db032/core/state_transition.go#L306-L306>
|
||||
///
|
||||
/// [`BlockEnv`]: revm_context::BlockEnv
|
||||
pub fn ensure_fees(
|
||||
call_gas_price: Option<U256>,
|
||||
call_max_fee: Option<U256>,
|
||||
call_priority_fee: Option<U256>,
|
||||
block_base_fee: U256,
|
||||
blob_versioned_hashes: Option<&[B256]>,
|
||||
max_fee_per_blob_gas: Option<U256>,
|
||||
block_blob_fee: Option<U256>,
|
||||
) -> Result<Self, CallFeesError> {
|
||||
/// Get the effective gas price of a transaction as specfified in EIP-1559 with relevant
|
||||
/// checks.
|
||||
fn get_effective_gas_price(
|
||||
max_fee_per_gas: Option<U256>,
|
||||
max_priority_fee_per_gas: Option<U256>,
|
||||
block_base_fee: U256,
|
||||
) -> Result<U256, CallFeesError> {
|
||||
match max_fee_per_gas {
|
||||
Some(max_fee) => {
|
||||
let max_priority_fee_per_gas = max_priority_fee_per_gas.unwrap_or(U256::ZERO);
|
||||
|
||||
// only enforce the fee cap if provided input is not zero
|
||||
if !(max_fee.is_zero() && max_priority_fee_per_gas.is_zero()) &&
|
||||
max_fee < block_base_fee
|
||||
{
|
||||
// `base_fee_per_gas` is greater than the `max_fee_per_gas`
|
||||
return Err(CallFeesError::FeeCapTooLow)
|
||||
}
|
||||
if max_fee < max_priority_fee_per_gas {
|
||||
return Err(
|
||||
// `max_priority_fee_per_gas` is greater than the `max_fee_per_gas`
|
||||
CallFeesError::TipAboveFeeCap,
|
||||
)
|
||||
}
|
||||
// ref <https://github.com/ethereum/go-ethereum/blob/0dd173a727dd2d2409b8e401b22e85d20c25b71f/internal/ethapi/transaction_args.go#L446-L446>
|
||||
Ok(min(
|
||||
max_fee,
|
||||
block_base_fee
|
||||
.checked_add(max_priority_fee_per_gas)
|
||||
.ok_or(CallFeesError::TipVeryHigh)?,
|
||||
))
|
||||
}
|
||||
None => Ok(block_base_fee
|
||||
.checked_add(max_priority_fee_per_gas.unwrap_or(U256::ZERO))
|
||||
.ok_or(CallFeesError::TipVeryHigh)?),
|
||||
}
|
||||
}
|
||||
|
||||
let has_blob_hashes =
|
||||
blob_versioned_hashes.as_ref().map(|blobs| !blobs.is_empty()).unwrap_or(false);
|
||||
|
||||
match (call_gas_price, call_max_fee, call_priority_fee, max_fee_per_blob_gas) {
|
||||
(gas_price, None, None, None) => {
|
||||
// either legacy transaction or no fee fields are specified
|
||||
// when no fields are specified, set gas price to zero
|
||||
let gas_price = gas_price.unwrap_or(U256::ZERO);
|
||||
Ok(Self {
|
||||
gas_price,
|
||||
max_priority_fee_per_gas: None,
|
||||
max_fee_per_blob_gas: has_blob_hashes.then_some(block_blob_fee).flatten(),
|
||||
})
|
||||
}
|
||||
(None, max_fee_per_gas, max_priority_fee_per_gas, None) => {
|
||||
// request for eip-1559 transaction
|
||||
let effective_gas_price = get_effective_gas_price(
|
||||
max_fee_per_gas,
|
||||
max_priority_fee_per_gas,
|
||||
block_base_fee,
|
||||
)?;
|
||||
let max_fee_per_blob_gas = has_blob_hashes.then_some(block_blob_fee).flatten();
|
||||
|
||||
Ok(Self {
|
||||
gas_price: effective_gas_price,
|
||||
max_priority_fee_per_gas,
|
||||
max_fee_per_blob_gas,
|
||||
})
|
||||
}
|
||||
(None, max_fee_per_gas, max_priority_fee_per_gas, Some(max_fee_per_blob_gas)) => {
|
||||
// request for eip-4844 transaction
|
||||
let effective_gas_price = get_effective_gas_price(
|
||||
max_fee_per_gas,
|
||||
max_priority_fee_per_gas,
|
||||
block_base_fee,
|
||||
)?;
|
||||
// Ensure blob_hashes are present
|
||||
if !has_blob_hashes {
|
||||
// Blob transaction but no blob hashes
|
||||
return Err(CallFeesError::BlobTransactionMissingBlobHashes)
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
gas_price: effective_gas_price,
|
||||
max_priority_fee_per_gas,
|
||||
max_fee_per_blob_gas: Some(max_fee_per_blob_gas),
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
// this fallback covers incompatible combinations of fields
|
||||
Err(CallFeesError::ConflictingFeeFieldsInRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error coming from decoding and validating transaction request fees.
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CallFeesError {
|
||||
/// Thrown when a call or transaction request (`eth_call`, `eth_estimateGas`,
|
||||
/// `eth_sendTransaction`) contains conflicting fields (legacy, EIP-1559)
|
||||
#[error("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")]
|
||||
ConflictingFeeFieldsInRequest,
|
||||
/// Thrown post London if the transaction's fee is less than the base fee of the block
|
||||
#[error("max fee per gas less than block base fee")]
|
||||
FeeCapTooLow,
|
||||
/// Thrown to ensure no one is able to specify a transaction with a tip higher than the total
|
||||
/// fee cap.
|
||||
#[error("max priority fee per gas higher than max fee per gas")]
|
||||
TipAboveFeeCap,
|
||||
/// A sanity error to avoid huge numbers specified in the tip field.
|
||||
#[error("max priority fee per gas higher than 2^256-1")]
|
||||
TipVeryHigh,
|
||||
/// Blob transaction has no versioned hashes
|
||||
#[error("blob transaction missing blob hashes")]
|
||||
BlobTransactionMissingBlobHashes,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloy_consensus::constants::GWEI_TO_WEI;
|
||||
|
||||
#[test]
|
||||
fn test_ensure_0_fallback() {
|
||||
let CallFees { gas_price, .. } =
|
||||
CallFees::ensure_fees(None, None, None, U256::from(99), None, None, Some(U256::ZERO))
|
||||
.unwrap();
|
||||
assert!(gas_price.is_zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ensure_max_fee_0_exception() {
|
||||
let CallFees { gas_price, .. } =
|
||||
CallFees::ensure_fees(None, Some(U256::ZERO), None, U256::from(99), None, None, None)
|
||||
.unwrap();
|
||||
assert!(gas_price.is_zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blob_fees() {
|
||||
let CallFees { gas_price, max_fee_per_blob_gas, .. } =
|
||||
CallFees::ensure_fees(None, None, None, U256::from(99), None, None, Some(U256::ZERO))
|
||||
.unwrap();
|
||||
assert!(gas_price.is_zero());
|
||||
assert_eq!(max_fee_per_blob_gas, None);
|
||||
|
||||
let CallFees { gas_price, max_fee_per_blob_gas, .. } = CallFees::ensure_fees(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
U256::from(99),
|
||||
Some(&[B256::from(U256::ZERO)]),
|
||||
None,
|
||||
Some(U256::from(99)),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(gas_price.is_zero());
|
||||
assert_eq!(max_fee_per_blob_gas, Some(U256::from(99)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_eip_1559_fees() {
|
||||
let CallFees { gas_price, .. } = CallFees::ensure_fees(
|
||||
None,
|
||||
Some(U256::from(25 * GWEI_TO_WEI)),
|
||||
Some(U256::from(15 * GWEI_TO_WEI)),
|
||||
U256::from(15 * GWEI_TO_WEI),
|
||||
None,
|
||||
None,
|
||||
Some(U256::ZERO),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(gas_price, U256::from(25 * GWEI_TO_WEI));
|
||||
|
||||
let CallFees { gas_price, .. } = CallFees::ensure_fees(
|
||||
None,
|
||||
Some(U256::from(25 * GWEI_TO_WEI)),
|
||||
Some(U256::from(5 * GWEI_TO_WEI)),
|
||||
U256::from(15 * GWEI_TO_WEI),
|
||||
None,
|
||||
None,
|
||||
Some(U256::ZERO),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(gas_price, U256::from(20 * GWEI_TO_WEI));
|
||||
|
||||
let CallFees { gas_price, .. } = CallFees::ensure_fees(
|
||||
None,
|
||||
Some(U256::from(30 * GWEI_TO_WEI)),
|
||||
Some(U256::from(30 * GWEI_TO_WEI)),
|
||||
U256::from(15 * GWEI_TO_WEI),
|
||||
None,
|
||||
None,
|
||||
Some(U256::ZERO),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(gas_price, U256::from(30 * GWEI_TO_WEI));
|
||||
|
||||
let call_fees = CallFees::ensure_fees(
|
||||
None,
|
||||
Some(U256::from(30 * GWEI_TO_WEI)),
|
||||
Some(U256::from(31 * GWEI_TO_WEI)),
|
||||
U256::from(15 * GWEI_TO_WEI),
|
||||
None,
|
||||
None,
|
||||
Some(U256::ZERO),
|
||||
);
|
||||
assert!(call_fees.is_err());
|
||||
|
||||
let call_fees = CallFees::ensure_fees(
|
||||
None,
|
||||
Some(U256::from(5 * GWEI_TO_WEI)),
|
||||
Some(U256::from(GWEI_TO_WEI)),
|
||||
U256::from(15 * GWEI_TO_WEI),
|
||||
None,
|
||||
None,
|
||||
Some(U256::ZERO),
|
||||
);
|
||||
assert!(call_fees.is_err());
|
||||
|
||||
let call_fees = CallFees::ensure_fees(
|
||||
None,
|
||||
Some(U256::MAX),
|
||||
Some(U256::MAX),
|
||||
U256::from(5 * GWEI_TO_WEI),
|
||||
None,
|
||||
None,
|
||||
Some(U256::ZERO),
|
||||
);
|
||||
assert!(call_fees.is_err());
|
||||
}
|
||||
}
|
||||
@@ -11,19 +11,19 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
pub mod block;
|
||||
mod fees;
|
||||
pub mod receipt;
|
||||
mod rpc;
|
||||
pub mod transaction;
|
||||
|
||||
pub use block::TryFromBlockResponse;
|
||||
pub use fees::{CallFees, CallFeesError};
|
||||
pub use receipt::TryFromReceiptResponse;
|
||||
pub use rpc::*;
|
||||
pub use transaction::{
|
||||
EthTxEnvError, IntoRpcTx, RpcConvert, RpcConverter, TransactionConversionError,
|
||||
TryFromTransactionResponse, TryIntoSimTx, TxInfoMapper,
|
||||
RpcConvert, RpcConverter, TransactionConversionError, TryFromTransactionResponse, TryIntoSimTx,
|
||||
TxInfoMapper,
|
||||
};
|
||||
|
||||
pub use alloy_evm::rpc::{CallFees, CallFeesError, EthTxEnvError, TryIntoTxEnv};
|
||||
|
||||
#[cfg(feature = "op")]
|
||||
pub use transaction::op::*;
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
//! Compatibility functions for rpc `Transaction` type.
|
||||
use crate::{
|
||||
fees::{CallFees, CallFeesError},
|
||||
RpcHeader, RpcReceipt, RpcTransaction, RpcTxReq, RpcTypes, SignableTxRequest,
|
||||
RpcHeader, RpcReceipt, RpcTransaction, RpcTxReq, RpcTypes, SignableTxRequest, TryIntoTxEnv,
|
||||
};
|
||||
use alloy_consensus::{
|
||||
error::ValueError, transaction::Recovered, EthereumTxEnvelope, Sealable, TxEip4844,
|
||||
};
|
||||
use alloy_network::Network;
|
||||
use alloy_primitives::{Address, TxKind, U256};
|
||||
use alloy_rpc_types_eth::{
|
||||
request::{TransactionInputError, TransactionRequest},
|
||||
Transaction, TransactionInfo,
|
||||
};
|
||||
use alloy_primitives::{Address, U256};
|
||||
use alloy_rpc_types_eth::{request::TransactionRequest, Transaction, TransactionInfo};
|
||||
use core::error;
|
||||
use dyn_clone::DynClone;
|
||||
use reth_evm::{
|
||||
revm::context_interface::{either::Either, Block},
|
||||
BlockEnvFor, ConfigureEvm, EvmEnvFor, TxEnvFor,
|
||||
};
|
||||
use reth_evm::{BlockEnvFor, ConfigureEvm, EvmEnvFor, TxEnvFor};
|
||||
use reth_primitives_traits::{
|
||||
BlockTy, HeaderTy, NodePrimitives, SealedBlock, SealedHeader, SealedHeaderFor, TransactionMeta,
|
||||
TxTy,
|
||||
};
|
||||
use revm_context::{BlockEnv, CfgEnv, TxEnv};
|
||||
use std::{convert::Infallible, error::Error, fmt::Debug, marker::PhantomData};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -462,7 +454,7 @@ where
|
||||
tx_req: TxReq,
|
||||
evm_env: &EvmEnvFor<Evm>,
|
||||
) -> Result<TxEnvFor<Evm>, Self::Error> {
|
||||
tx_req.try_into_tx_env(&evm_env.cfg_env, &evm_env.block_env)
|
||||
tx_req.try_into_tx_env(evm_env)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,122 +483,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `self` into `T`.
|
||||
///
|
||||
/// Should create an executable transaction environment using [`TransactionRequest`].
|
||||
pub trait TryIntoTxEnv<T, BlockEnv = reth_evm::revm::context::BlockEnv> {
|
||||
/// An associated error that can occur during the conversion.
|
||||
type Err;
|
||||
|
||||
/// Performs the conversion.
|
||||
fn try_into_tx_env<Spec>(
|
||||
self,
|
||||
cfg_env: &CfgEnv<Spec>,
|
||||
block_env: &BlockEnv,
|
||||
) -> Result<T, Self::Err>;
|
||||
}
|
||||
|
||||
/// An Ethereum specific transaction environment error than can occur during conversion from
|
||||
/// [`TransactionRequest`].
|
||||
#[derive(Debug, Error)]
|
||||
pub enum EthTxEnvError {
|
||||
/// Error while decoding or validating transaction request fees.
|
||||
#[error(transparent)]
|
||||
CallFees(#[from] CallFeesError),
|
||||
/// Both data and input fields are set and not equal.
|
||||
#[error(transparent)]
|
||||
Input(#[from] TransactionInputError),
|
||||
}
|
||||
|
||||
impl TryIntoTxEnv<TxEnv> for TransactionRequest {
|
||||
type Err = EthTxEnvError;
|
||||
|
||||
fn try_into_tx_env<Spec>(
|
||||
self,
|
||||
cfg_env: &CfgEnv<Spec>,
|
||||
block_env: &BlockEnv,
|
||||
) -> Result<TxEnv, Self::Err> {
|
||||
// Ensure that if versioned hashes are set, they're not empty
|
||||
if self.blob_versioned_hashes.as_ref().is_some_and(|hashes| hashes.is_empty()) {
|
||||
return Err(CallFeesError::BlobTransactionMissingBlobHashes.into())
|
||||
}
|
||||
|
||||
let tx_type = self.minimal_tx_type() as u8;
|
||||
|
||||
let Self {
|
||||
from,
|
||||
to,
|
||||
gas_price,
|
||||
max_fee_per_gas,
|
||||
max_priority_fee_per_gas,
|
||||
gas,
|
||||
value,
|
||||
input,
|
||||
nonce,
|
||||
access_list,
|
||||
chain_id,
|
||||
blob_versioned_hashes,
|
||||
max_fee_per_blob_gas,
|
||||
authorization_list,
|
||||
transaction_type: _,
|
||||
sidecar: _,
|
||||
} = self;
|
||||
|
||||
let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } =
|
||||
CallFees::ensure_fees(
|
||||
gas_price.map(U256::from),
|
||||
max_fee_per_gas.map(U256::from),
|
||||
max_priority_fee_per_gas.map(U256::from),
|
||||
U256::from(block_env.basefee),
|
||||
blob_versioned_hashes.as_deref(),
|
||||
max_fee_per_blob_gas.map(U256::from),
|
||||
block_env.blob_gasprice().map(U256::from),
|
||||
)?;
|
||||
|
||||
let gas_limit = gas.unwrap_or(
|
||||
// Use maximum allowed gas limit. The reason for this
|
||||
// is that both Erigon and Geth use pre-configured gas cap even if
|
||||
// it's possible to derive the gas limit from the block:
|
||||
// <https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/cmd/rpcdaemon/commands/trace_adhoc.go#L956
|
||||
// https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/eth/ethconfig/config.go#L94>
|
||||
block_env.gas_limit,
|
||||
);
|
||||
|
||||
let chain_id = chain_id.unwrap_or(cfg_env.chain_id);
|
||||
|
||||
let caller = from.unwrap_or_default();
|
||||
|
||||
let nonce = nonce.unwrap_or_default();
|
||||
|
||||
let env = TxEnv {
|
||||
tx_type,
|
||||
gas_limit,
|
||||
nonce,
|
||||
caller,
|
||||
gas_price: gas_price.saturating_to(),
|
||||
gas_priority_fee: max_priority_fee_per_gas.map(|v| v.saturating_to()),
|
||||
kind: to.unwrap_or(TxKind::Create),
|
||||
value: value.unwrap_or_default(),
|
||||
data: input.try_into_unique_input().map_err(EthTxEnvError::from)?.unwrap_or_default(),
|
||||
chain_id: Some(chain_id),
|
||||
access_list: access_list.unwrap_or_default(),
|
||||
// EIP-4844 fields
|
||||
blob_hashes: blob_versioned_hashes.unwrap_or_default(),
|
||||
max_fee_per_blob_gas: max_fee_per_blob_gas
|
||||
.map(|v| v.saturating_to())
|
||||
.unwrap_or_default(),
|
||||
// EIP-7702 fields
|
||||
authorization_list: authorization_list
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(Either::Left)
|
||||
.collect(),
|
||||
};
|
||||
|
||||
Ok(env)
|
||||
}
|
||||
}
|
||||
|
||||
/// Conversion into transaction RPC response failed.
|
||||
#[derive(Debug, Clone, Error)]
|
||||
#[error("Failed to convert transaction into RPC response: {0}")]
|
||||
@@ -990,13 +866,12 @@ where
|
||||
pub mod op {
|
||||
use super::*;
|
||||
use alloy_consensus::SignableTransaction;
|
||||
use alloy_primitives::{Address, Bytes, Signature};
|
||||
use alloy_signer::Signature;
|
||||
use op_alloy_consensus::{
|
||||
transaction::{OpDepositInfo, OpTransactionInfo},
|
||||
OpTxEnvelope,
|
||||
};
|
||||
use op_alloy_rpc_types::OpTransactionRequest;
|
||||
use op_revm::OpTransaction;
|
||||
use reth_optimism_primitives::DepositReceipt;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_storage_api::{errors::ProviderError, ReceiptProvider};
|
||||
@@ -1054,22 +929,6 @@ pub mod op {
|
||||
Ok(tx.into_signed(signature).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryIntoTxEnv<OpTransaction<TxEnv>> for OpTransactionRequest {
|
||||
type Err = EthTxEnvError;
|
||||
|
||||
fn try_into_tx_env<Spec>(
|
||||
self,
|
||||
cfg_env: &CfgEnv<Spec>,
|
||||
block_env: &BlockEnv,
|
||||
) -> Result<OpTransaction<TxEnv>, Self::Err> {
|
||||
Ok(OpTransaction {
|
||||
base: self.as_ref().clone().try_into_tx_env(cfg_env, block_env)?,
|
||||
enveloped_tx: Some(Bytes::new()),
|
||||
deposit: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for converting network transaction responses to primitive transaction types.
|
||||
@@ -1146,8 +1005,6 @@ mod transaction_response_tests {
|
||||
#[cfg(feature = "op")]
|
||||
mod op {
|
||||
use super::*;
|
||||
use crate::transaction::TryIntoTxEnv;
|
||||
use revm_context::{BlockEnv, CfgEnv};
|
||||
|
||||
#[test]
|
||||
fn test_optimism_transaction_conversion() {
|
||||
@@ -1180,23 +1037,5 @@ mod transaction_response_tests {
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_op_into_tx_env() {
|
||||
use op_alloy_rpc_types::OpTransactionRequest;
|
||||
use op_revm::{transaction::OpTxTr, OpSpecId};
|
||||
use revm_context::Transaction;
|
||||
|
||||
let s = r#"{"from":"0x0000000000000000000000000000000000000000","to":"0x6d362b9c3ab68c0b7c79e8a714f1d7f3af63655f","input":"0x1626ba7ec8ee0d506e864589b799a645ddb88b08f5d39e8049f9f702b3b61fa15e55fc73000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000550000002d6db27c52e3c11c1cf24072004ac75cba49b25bf45f513902e469755e1f3bf2ca8324ad16930b0a965c012a24bb1101f876ebebac047bd3b6bf610205a27171eaaeffe4b5e5589936f4e542d637b627311b0000000000000000000000","data":"0x1626ba7ec8ee0d506e864589b799a645ddb88b08f5d39e8049f9f702b3b61fa15e55fc73000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000550000002d6db27c52e3c11c1cf24072004ac75cba49b25bf45f513902e469755e1f3bf2ca8324ad16930b0a965c012a24bb1101f876ebebac047bd3b6bf610205a27171eaaeffe4b5e5589936f4e542d637b627311b0000000000000000000000","chainId":"0x7a69"}"#;
|
||||
|
||||
let req: OpTransactionRequest = serde_json::from_str(s).unwrap();
|
||||
|
||||
let cfg = CfgEnv::<OpSpecId>::default();
|
||||
let block_env = BlockEnv::default();
|
||||
let tx_env = req.try_into_tx_env(&cfg, &block_env).unwrap();
|
||||
assert_eq!(tx_env.gas_limit(), block_env.gas_limit);
|
||||
assert_eq!(tx_env.gas_price(), 0);
|
||||
assert!(tx_env.enveloped_tx().unwrap().is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@ use crate::{
|
||||
primitives::{CustomHeader, CustomTransaction},
|
||||
};
|
||||
use alloy_consensus::error::ValueError;
|
||||
use alloy_evm::EvmEnv;
|
||||
use alloy_network::TxSigner;
|
||||
use op_alloy_consensus::OpTxEnvelope;
|
||||
use op_alloy_rpc_types::{OpTransactionReceipt, OpTransactionRequest};
|
||||
use reth_op::rpc::RpcTypes;
|
||||
use reth_rpc_api::eth::{
|
||||
transaction::TryIntoTxEnv, EthTxEnvError, SignTxRequestError, SignableTxRequest, TryIntoSimTx,
|
||||
EthTxEnvError, SignTxRequestError, SignableTxRequest, TryIntoSimTx, TryIntoTxEnv,
|
||||
};
|
||||
use revm::context::{BlockEnv, CfgEnv};
|
||||
use revm::context::BlockEnv;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
#[non_exhaustive]
|
||||
@@ -34,10 +35,9 @@ impl TryIntoTxEnv<CustomTxEnv> for OpTransactionRequest {
|
||||
|
||||
fn try_into_tx_env<Spec>(
|
||||
self,
|
||||
cfg_env: &CfgEnv<Spec>,
|
||||
block_env: &BlockEnv,
|
||||
evm_env: &EvmEnv<Spec, BlockEnv>,
|
||||
) -> Result<CustomTxEnv, Self::Err> {
|
||||
Ok(CustomTxEnv::Op(self.try_into_tx_env(cfg_env, block_env)?))
|
||||
Ok(CustomTxEnv::Op(self.try_into_tx_env(evm_env)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user