mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-08 23:08:19 -05:00
feat!: replace TransactionSigned with alloy's (#15768)
This commit is contained in:
323
Cargo.lock
generated
323
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
56
Cargo.toml
56
Cargo.toml
@@ -468,34 +468,34 @@ alloy-trie = { version = "0.8.1", default-features = false }
|
||||
|
||||
alloy-hardforks = "0.2.0"
|
||||
|
||||
alloy-consensus = { version = "0.15.0", default-features = false }
|
||||
alloy-contract = { version = "0.15.0", default-features = false }
|
||||
alloy-eips = { version = "0.15.0", default-features = false }
|
||||
alloy-genesis = { version = "0.15.0", default-features = false }
|
||||
alloy-json-rpc = { version = "0.15.0", default-features = false }
|
||||
alloy-network = { version = "0.15.0", default-features = false }
|
||||
alloy-network-primitives = { version = "0.15.0", default-features = false }
|
||||
alloy-node-bindings = { version = "0.15.0", default-features = false }
|
||||
alloy-provider = { version = "0.15.0", features = ["reqwest"], default-features = false }
|
||||
alloy-pubsub = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-client = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types = { version = "0.15.0", features = ["eth"], default-features = false }
|
||||
alloy-rpc-types-admin = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-anvil = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-beacon = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-debug = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-engine = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-eth = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-mev = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-trace = { version = "0.15.0", default-features = false }
|
||||
alloy-rpc-types-txpool = { version = "0.15.0", default-features = false }
|
||||
alloy-serde = { version = "0.15.0", default-features = false }
|
||||
alloy-signer = { version = "0.15.0", default-features = false }
|
||||
alloy-signer-local = { version = "0.15.0", default-features = false }
|
||||
alloy-transport = { version = "0.15.0" }
|
||||
alloy-transport-http = { version = "0.15.0", features = ["reqwest-rustls-tls"], default-features = false }
|
||||
alloy-transport-ipc = { version = "0.15.0", default-features = false }
|
||||
alloy-transport-ws = { version = "0.15.0", default-features = false }
|
||||
alloy-consensus = { version = "0.15.3", default-features = false }
|
||||
alloy-contract = { version = "0.15.3", default-features = false }
|
||||
alloy-eips = { version = "0.15.3", default-features = false }
|
||||
alloy-genesis = { version = "0.15.3", default-features = false }
|
||||
alloy-json-rpc = { version = "0.15.3", default-features = false }
|
||||
alloy-network = { version = "0.15.3", default-features = false }
|
||||
alloy-network-primitives = { version = "0.15.3", default-features = false }
|
||||
alloy-node-bindings = { version = "0.15.3", default-features = false }
|
||||
alloy-provider = { version = "0.15.3", features = ["reqwest"], default-features = false }
|
||||
alloy-pubsub = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-client = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types = { version = "0.15.3", features = ["eth"], default-features = false }
|
||||
alloy-rpc-types-admin = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-anvil = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-beacon = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-debug = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-engine = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-eth = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-mev = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-trace = { version = "0.15.3", default-features = false }
|
||||
alloy-rpc-types-txpool = { version = "0.15.3", default-features = false }
|
||||
alloy-serde = { version = "0.15.3", default-features = false }
|
||||
alloy-signer = { version = "0.15.3", default-features = false }
|
||||
alloy-signer-local = { version = "0.15.3", default-features = false }
|
||||
alloy-transport = { version = "0.15.3" }
|
||||
alloy-transport-http = { version = "0.15.3", features = ["reqwest-rustls-tls"], default-features = false }
|
||||
alloy-transport-ipc = { version = "0.15.3", default-features = false }
|
||||
alloy-transport-ws = { version = "0.15.3", default-features = false }
|
||||
|
||||
# op
|
||||
alloy-op-evm = { version = "0.6.0", default-features = false }
|
||||
|
||||
@@ -215,8 +215,8 @@ impl<T: Clone + Sync + Send + 'static> Stream for ForkChoiceStream<T> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloy_consensus::BlockBody;
|
||||
use alloy_primitives::{b256, B256};
|
||||
use alloy_consensus::{BlockBody, SignableTransaction, TxLegacy};
|
||||
use alloy_primitives::{b256, Signature, B256};
|
||||
use reth_ethereum_primitives::{Receipt, TransactionSigned, TxType};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_primitives_traits::SealedBlock;
|
||||
@@ -305,7 +305,7 @@ mod tests {
|
||||
let block2_hash = B256::new([0x02; 32]);
|
||||
|
||||
// Create a default transaction to include in block1's transactions.
|
||||
let tx = TransactionSigned::default();
|
||||
let tx = TxLegacy::default().into_signed(Signature::test_signature()).into();
|
||||
body.transactions.push(tx);
|
||||
|
||||
let block = SealedBlock::<alloy_consensus::Block<TransactionSigned>>::from_sealed_parts(
|
||||
@@ -373,7 +373,7 @@ mod tests {
|
||||
fn test_block_receipts_reorg() {
|
||||
// Define block1 for the old chain segment, which will be reverted.
|
||||
let mut body = BlockBody::<TransactionSigned>::default();
|
||||
body.transactions.push(TransactionSigned::default());
|
||||
body.transactions.push(TxLegacy::default().into_signed(Signature::test_signature()).into());
|
||||
let mut old_block1 =
|
||||
SealedBlock::<alloy_consensus::Block<TransactionSigned>>::from_sealed_parts(
|
||||
SealedHeader::seal_slow(alloy_consensus::Header::default()),
|
||||
@@ -402,7 +402,7 @@ mod tests {
|
||||
|
||||
// Define block2 for the new chain segment, which will be committed.
|
||||
let mut body = BlockBody::<TransactionSigned>::default();
|
||||
body.transactions.push(TransactionSigned::default());
|
||||
body.transactions.push(TxLegacy::default().into_signed(Signature::test_signature()).into());
|
||||
let mut new_block1 =
|
||||
SealedBlock::<alloy_consensus::Block<TransactionSigned>>::from_sealed_parts(
|
||||
SealedHeader::seal_slow(alloy_consensus::Header::default()),
|
||||
|
||||
@@ -63,7 +63,7 @@ macro_rules! compact_types {
|
||||
pub static IDENTIFIER_TYPE: std::sync::LazyLock<std::collections::HashSet<String>> = std::sync::LazyLock::new(|| {
|
||||
let mut map = std::collections::HashSet::new();
|
||||
$(
|
||||
map.insert(type_name::<$id_ty>());
|
||||
map.insert(type_name::<$id_ty>());
|
||||
)*
|
||||
map
|
||||
});
|
||||
@@ -279,6 +279,15 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the type name for the given type.
|
||||
pub fn type_name<T>() -> String {
|
||||
std::any::type_name::<T>().split("::").last().unwrap_or(std::any::type_name::<T>()).to_string()
|
||||
// With alloy type transition <https://github.com/paradigmxyz/reth/pull/15768> the types are renamed, we map them here to the original name so that test vector files remain consistent
|
||||
let name = std::any::type_name::<T>();
|
||||
match name {
|
||||
"alloy_consensus::transaction::typed::EthereumTypedTransaction<alloy_consensus::transaction::eip4844::TxEip4844>" => "Transaction".to_string(),
|
||||
"alloy_consensus::transaction::envelope::EthereumTxEnvelope<alloy_consensus::transaction::eip4844::TxEip4844>" => "TransactionSigned".to_string(),
|
||||
name => {
|
||||
name.split("::").last().unwrap_or(std::any::type_name::<T>()).to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Command for debugging block building.
|
||||
use alloy_consensus::{BlockHeader, TxEip4844};
|
||||
use alloy_consensus::BlockHeader;
|
||||
use alloy_eips::{
|
||||
eip2718::Encodable2718,
|
||||
eip4844::{env_settings::EnvKzgSettings, BlobTransactionSidecar},
|
||||
@@ -17,7 +17,7 @@ use reth_cli_runner::CliContext;
|
||||
use reth_consensus::{Consensus, FullConsensus};
|
||||
use reth_errors::{ConsensusError, RethResult};
|
||||
use reth_ethereum_payload_builder::EthereumBuilderConfig;
|
||||
use reth_ethereum_primitives::{EthPrimitives, Transaction, TransactionSigned};
|
||||
use reth_ethereum_primitives::{EthPrimitives, TransactionSigned};
|
||||
use reth_evm::execute::{BlockExecutorProvider, Executor};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_fs_util as fs;
|
||||
@@ -146,14 +146,14 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
|
||||
.try_clone_into_recovered()
|
||||
.map_err(|e| eyre::eyre!("failed to recover tx: {e}"))?;
|
||||
|
||||
let encoded_length = match transaction.transaction() {
|
||||
Transaction::Eip4844(TxEip4844 { blob_versioned_hashes, .. }) => {
|
||||
let encoded_length = match transaction.inner() {
|
||||
TransactionSigned::Eip4844(tx) => {
|
||||
let blobs_bundle = blobs_bundle.as_mut().ok_or_else(|| {
|
||||
eyre::eyre!("encountered a blob tx. `--blobs-bundle-path` must be provided")
|
||||
})?;
|
||||
|
||||
let sidecar: BlobTransactionSidecar =
|
||||
blobs_bundle.pop_sidecar(blob_versioned_hashes.len());
|
||||
blobs_bundle.pop_sidecar(tx.tx().blob_versioned_hashes.len());
|
||||
|
||||
let pooled = transaction
|
||||
.clone()
|
||||
|
||||
@@ -29,7 +29,6 @@ use reth_evm_ethereum::EthEvmConfig;
|
||||
use reth_payload_builder::{EthBuiltPayload, EthPayloadBuilderAttributes};
|
||||
use reth_payload_builder_primitives::PayloadBuilderError;
|
||||
use reth_payload_primitives::PayloadBuilderAttributes;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_revm::{database::StateProviderDatabase, db::State};
|
||||
use reth_storage_api::StateProviderFactory;
|
||||
use reth_transaction_pool::{
|
||||
@@ -218,7 +217,7 @@ where
|
||||
// There's only limited amount of blob space available per block, so we need to check if
|
||||
// the EIP-4844 can still fit in the block
|
||||
if let Some(blob_tx) = tx.as_eip4844() {
|
||||
let tx_blob_count = blob_tx.blob_versioned_hashes.len() as u64;
|
||||
let tx_blob_count = blob_tx.tx().blob_versioned_hashes.len() as u64;
|
||||
|
||||
if block_blob_count + tx_blob_count > max_blob_count {
|
||||
// we can't fit this _blob_ transaction into the block, so we mark it as
|
||||
@@ -266,7 +265,7 @@ where
|
||||
|
||||
// add to the total blob gas used if the transaction successfully executed
|
||||
if let Some(blob_tx) = tx.as_eip4844() {
|
||||
block_blob_count += blob_tx.blob_versioned_hashes.len() as u64;
|
||||
block_blob_count += blob_tx.tx().blob_versioned_hashes.len() as u64;
|
||||
|
||||
// if we've reached the max blob count, we can skip blob txs entirely
|
||||
if block_blob_count == max_blob_count {
|
||||
|
||||
@@ -18,25 +18,19 @@ reth-primitives-traits.workspace = true
|
||||
reth-zstd-compressors = { workspace = true, optional = true }
|
||||
|
||||
# ethereum
|
||||
alloy-evm.workspace = true
|
||||
alloy-eips = { workspace = true, features = ["k256"] }
|
||||
alloy-primitives.workspace = true
|
||||
alloy-network = { workspace = true, optional = true }
|
||||
alloy-consensus = { workspace = true, features = ["serde"] }
|
||||
alloy-rlp.workspace = true
|
||||
alloy-rpc-types-eth = { workspace = true, optional = true }
|
||||
revm-context.workspace = true
|
||||
|
||||
# misc
|
||||
arbitrary = { workspace = true, optional = true, features = ["derive"] }
|
||||
derive_more.workspace = true
|
||||
modular-bitfield = { workspace = true, optional = true }
|
||||
rand_08 = { workspace = true, optional = true }
|
||||
secp256k1 = { workspace = true, optional = true, features = ["rand"] }
|
||||
serde = { workspace = true, optional = true }
|
||||
serde_with = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
derive_more.workspace = true
|
||||
arbitrary.workspace = true
|
||||
bincode.workspace = true
|
||||
proptest.workspace = true
|
||||
@@ -44,7 +38,6 @@ proptest-arbitrary-interop.workspace = true
|
||||
rand_08.workspace = true
|
||||
rand.workspace = true
|
||||
reth-codecs = { workspace = true, features = ["test-utils"] }
|
||||
reth-testing-utils.workspace = true
|
||||
reth-zstd-compressors.workspace = true
|
||||
secp256k1 = { workspace = true, features = ["rand"] }
|
||||
test-fuzz.workspace = true
|
||||
@@ -56,7 +49,6 @@ test-utils = [
|
||||
"reth-codecs?/test-utils",
|
||||
"reth-primitives-traits/test-utils",
|
||||
]
|
||||
alloy-compat = ["dep:alloy-network", "dep:alloy-rpc-types-eth"]
|
||||
std = [
|
||||
"alloy-consensus/std",
|
||||
"alloy-primitives/std",
|
||||
@@ -66,11 +58,8 @@ std = [
|
||||
"serde?/std",
|
||||
"alloy-eips/std",
|
||||
"derive_more/std",
|
||||
"secp256k1?/std",
|
||||
"alloy-rpc-types-eth?/std",
|
||||
"revm-context/std",
|
||||
"alloy-evm/std",
|
||||
"serde_with?/std",
|
||||
"secp256k1/std",
|
||||
]
|
||||
reth-codec = [
|
||||
"std",
|
||||
@@ -80,14 +69,12 @@ reth-codec = [
|
||||
]
|
||||
arbitrary = [
|
||||
"dep:arbitrary",
|
||||
"dep:rand_08",
|
||||
"dep:secp256k1",
|
||||
"alloy-consensus/arbitrary",
|
||||
"alloy-consensus/k256",
|
||||
"alloy-primitives/arbitrary",
|
||||
"reth-codecs?/arbitrary",
|
||||
"reth-primitives-traits/arbitrary",
|
||||
"alloy-eips/arbitrary",
|
||||
"alloy-rpc-types-eth?/arbitrary",
|
||||
]
|
||||
serde-bincode-compat = [
|
||||
"dep:serde_with",
|
||||
@@ -100,11 +87,9 @@ serde = [
|
||||
"alloy-consensus/serde",
|
||||
"alloy-eips/serde",
|
||||
"alloy-primitives/serde",
|
||||
"alloy-rpc-types-eth?/serde",
|
||||
"rand_08?/serde",
|
||||
"reth-codecs?/serde",
|
||||
"reth-primitives-traits/serde",
|
||||
"revm-context/serde",
|
||||
"secp256k1?/serde",
|
||||
"rand/serde",
|
||||
"rand_08/serde",
|
||||
"secp256k1/serde",
|
||||
]
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
//! Common conversions from alloy types.
|
||||
|
||||
use crate::{Transaction, TransactionSigned};
|
||||
use alloc::string::ToString;
|
||||
use alloy_consensus::TxEnvelope;
|
||||
use alloy_network::{AnyRpcTransaction, AnyTxEnvelope};
|
||||
use alloy_rpc_types_eth::Transaction as AlloyRpcTransaction;
|
||||
|
||||
impl TryFrom<AnyRpcTransaction> for TransactionSigned {
|
||||
type Error = alloy_rpc_types_eth::ConversionError;
|
||||
|
||||
fn try_from(tx: AnyRpcTransaction) -> Result<Self, Self::Error> {
|
||||
use alloy_rpc_types_eth::ConversionError;
|
||||
|
||||
let tx = tx.into_inner();
|
||||
|
||||
let (transaction, signature, hash) = match tx.inner.into_inner() {
|
||||
AnyTxEnvelope::Ethereum(TxEnvelope::Legacy(tx)) => {
|
||||
let (tx, signature, hash) = tx.into_parts();
|
||||
(Transaction::Legacy(tx), signature, hash)
|
||||
}
|
||||
AnyTxEnvelope::Ethereum(TxEnvelope::Eip2930(tx)) => {
|
||||
let (tx, signature, hash) = tx.into_parts();
|
||||
(Transaction::Eip2930(tx), signature, hash)
|
||||
}
|
||||
AnyTxEnvelope::Ethereum(TxEnvelope::Eip1559(tx)) => {
|
||||
let (tx, signature, hash) = tx.into_parts();
|
||||
(Transaction::Eip1559(tx), signature, hash)
|
||||
}
|
||||
AnyTxEnvelope::Ethereum(TxEnvelope::Eip4844(tx)) => {
|
||||
let (tx, signature, hash) = tx.into_parts();
|
||||
(Transaction::Eip4844(tx.into()), signature, hash)
|
||||
}
|
||||
AnyTxEnvelope::Ethereum(TxEnvelope::Eip7702(tx)) => {
|
||||
let (tx, signature, hash) = tx.into_parts();
|
||||
(Transaction::Eip7702(tx), signature, hash)
|
||||
}
|
||||
_ => return Err(ConversionError::Custom("unknown transaction type".to_string())),
|
||||
};
|
||||
|
||||
Ok(Self::new(transaction, signature, hash))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<AlloyRpcTransaction<T>> for TransactionSigned
|
||||
where
|
||||
Self: From<T>,
|
||||
{
|
||||
fn from(value: AlloyRpcTransaction<T>) -> Self {
|
||||
value.inner.into_inner().into()
|
||||
}
|
||||
}
|
||||
@@ -14,16 +14,24 @@ extern crate alloc;
|
||||
mod receipt;
|
||||
pub use receipt::*;
|
||||
|
||||
/// Kept for concistency tests
|
||||
#[cfg(test)]
|
||||
mod transaction;
|
||||
pub use transaction::*;
|
||||
|
||||
#[cfg(feature = "alloy-compat")]
|
||||
mod alloy_compat;
|
||||
use alloy_consensus::TxEip4844;
|
||||
pub use alloy_consensus::{transaction::PooledTransaction, TxType};
|
||||
|
||||
/// Typed Transaction type without a signature
|
||||
pub type Transaction = alloy_consensus::EthereumTypedTransaction<TxEip4844>;
|
||||
|
||||
/// Signed transaction.
|
||||
pub type TransactionSigned = alloy_consensus::EthereumTxEnvelope<TxEip4844>;
|
||||
|
||||
/// Bincode-compatible serde implementations.
|
||||
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
|
||||
pub mod serde_bincode_compat {
|
||||
pub use super::{receipt::serde_bincode_compat::*, transaction::serde_bincode_compat::*};
|
||||
pub use super::receipt::serde_bincode_compat::*;
|
||||
pub use alloy_consensus::serde_bincode_compat::transaction::*;
|
||||
}
|
||||
|
||||
/// Type alias for the ethereum block
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
//! This file contains the legacy reth `TransactionSigned` type that has been replaced with
|
||||
//! alloy's TxEnvelope To test for consistency this is kept
|
||||
|
||||
use alloc::vec::Vec;
|
||||
pub use alloy_consensus::{transaction::PooledTransaction, TxType};
|
||||
use alloy_consensus::{
|
||||
transaction::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx},
|
||||
BlobTransactionSidecar, EthereumTxEnvelope, SignableTransaction, Signed, TxEip1559, TxEip2930,
|
||||
TxEip4844, TxEip4844Variant, TxEip4844WithSidecar, TxEip7702, TxEnvelope, TxLegacy, Typed2718,
|
||||
TypedTransaction,
|
||||
EthereumTxEnvelope, SignableTransaction, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip7702,
|
||||
TxLegacy, TxType, Typed2718,
|
||||
};
|
||||
use alloy_eips::{
|
||||
eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718},
|
||||
eip2930::AccessList,
|
||||
eip7702::SignedAuthorization,
|
||||
};
|
||||
use alloy_evm::{FromRecoveredTx, FromTxWithEncoded};
|
||||
use alloy_primitives::{
|
||||
bytes::BufMut, keccak256, Address, Bytes, ChainId, Signature, TxHash, TxKind, B256, U256,
|
||||
};
|
||||
@@ -20,10 +20,9 @@ use core::hash::{Hash, Hasher};
|
||||
use reth_primitives_traits::{
|
||||
crypto::secp256k1::{recover_signer, recover_signer_unchecked},
|
||||
sync::OnceLock,
|
||||
transaction::{error::TransactionConversionError, signed::RecoveryError},
|
||||
transaction::signed::RecoveryError,
|
||||
InMemorySize, SignedTransaction,
|
||||
};
|
||||
use revm_context::TxEnv;
|
||||
|
||||
macro_rules! delegate {
|
||||
($self:expr => $tx:ident.$method:ident($($arg:expr),*)) => {
|
||||
@@ -37,19 +36,6 @@ macro_rules! delegate {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from_signed {
|
||||
($($tx:ident),*) => {
|
||||
$(
|
||||
impl From<Signed<$tx>> for TransactionSigned {
|
||||
fn from(value: Signed<$tx>) -> Self {
|
||||
let(tx,sig,hash) = value.into_parts();
|
||||
Self::new(tx.into(), sig, hash)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
/// A raw transaction.
|
||||
///
|
||||
/// Transaction types were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718).
|
||||
@@ -117,17 +103,6 @@ impl Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
/// This sets the transaction's nonce.
|
||||
pub const fn set_nonce(&mut self, nonce: u64) {
|
||||
match self {
|
||||
Self::Legacy(tx) => tx.nonce = nonce,
|
||||
Self::Eip2930(tx) => tx.nonce = nonce,
|
||||
Self::Eip1559(tx) => tx.nonce = nonce,
|
||||
Self::Eip4844(tx) => tx.nonce = nonce,
|
||||
Self::Eip7702(tx) => tx.nonce = nonce,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
const fn input_mut(&mut self) -> &mut Bytes {
|
||||
match self {
|
||||
@@ -290,18 +265,6 @@ impl reth_codecs::Compact for Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TypedTransaction> for Transaction {
|
||||
fn from(value: TypedTransaction) -> Self {
|
||||
match value {
|
||||
TypedTransaction::Legacy(tx) => Self::Legacy(tx),
|
||||
TypedTransaction::Eip2930(tx) => Self::Eip2930(tx),
|
||||
TypedTransaction::Eip1559(tx) => Self::Eip1559(tx),
|
||||
TypedTransaction::Eip4844(tx) => Self::Eip4844(tx.into()),
|
||||
TypedTransaction::Eip7702(tx) => Self::Eip7702(tx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RlpEcdsaEncodableTx for Transaction {
|
||||
fn rlp_encoded_fields_length(&self) -> usize {
|
||||
delegate!(self => tx.rlp_encoded_fields_length())
|
||||
@@ -355,21 +318,10 @@ pub struct TransactionSigned {
|
||||
transaction: Transaction,
|
||||
}
|
||||
|
||||
impl Default for TransactionSigned {
|
||||
fn default() -> Self {
|
||||
Self::new_unhashed(Transaction::Legacy(Default::default()), Signature::test_signature())
|
||||
}
|
||||
}
|
||||
|
||||
impl TransactionSigned {
|
||||
fn recalculate_hash(&self) -> B256 {
|
||||
keccak256(self.encoded_2718())
|
||||
}
|
||||
|
||||
/// Returns the signature of the transaction
|
||||
pub const fn signature(&self) -> &Signature {
|
||||
&self.signature
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for TransactionSigned {
|
||||
@@ -393,75 +345,12 @@ impl TransactionSigned {
|
||||
Self { hash: hash.into(), signature, transaction }
|
||||
}
|
||||
|
||||
/// Consumes the type and returns the transaction.
|
||||
#[inline]
|
||||
pub fn into_transaction(self) -> Transaction {
|
||||
self.transaction
|
||||
}
|
||||
|
||||
/// Returns the transaction.
|
||||
#[inline]
|
||||
pub const fn transaction(&self) -> &Transaction {
|
||||
&self.transaction
|
||||
}
|
||||
|
||||
/// Returns the transaction hash.
|
||||
#[inline]
|
||||
pub fn hash(&self) -> &B256 {
|
||||
self.hash.get_or_init(|| self.recalculate_hash())
|
||||
}
|
||||
|
||||
/// Creates a new signed transaction from the given transaction and signature without the hash.
|
||||
///
|
||||
/// Note: this only calculates the hash on the first [`TransactionSigned::hash`] call.
|
||||
pub fn new_unhashed(transaction: Transaction, signature: Signature) -> Self {
|
||||
Self { hash: Default::default(), signature, transaction }
|
||||
}
|
||||
|
||||
/// Splits the `TransactionSigned` into its transaction and signature.
|
||||
pub fn split(self) -> (Transaction, Signature) {
|
||||
(self.transaction, self.signature)
|
||||
}
|
||||
|
||||
/// Converts from an EIP-4844 transaction to a [`PooledTransaction`] with the given sidecar.
|
||||
///
|
||||
/// Returns an `Err` containing the original `TransactionSigned` if the transaction is not
|
||||
/// EIP-4844.
|
||||
pub fn try_into_pooled_eip4844(
|
||||
self,
|
||||
sidecar: BlobTransactionSidecar,
|
||||
) -> Result<PooledTransaction, Self> {
|
||||
let hash = *self.tx_hash();
|
||||
Ok(match self {
|
||||
// If the transaction is an EIP-4844 transaction...
|
||||
Self { transaction: Transaction::Eip4844(tx), signature, .. } => {
|
||||
// Construct a pooled eip488 tx with the provided sidecar.
|
||||
PooledTransaction::Eip4844(Signed::new_unchecked(
|
||||
TxEip4844WithSidecar { tx, sidecar },
|
||||
signature,
|
||||
hash,
|
||||
))
|
||||
}
|
||||
// If the transaction is not EIP-4844, return an error with the original
|
||||
// transaction.
|
||||
_ => return Err(self),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the [`TxEip4844`] if the transaction is an EIP-4844 transaction.
|
||||
pub const fn as_eip4844(&self) -> Option<&TxEip4844> {
|
||||
match &self.transaction {
|
||||
Transaction::Eip4844(tx) => Some(tx),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides mutable access to the transaction.
|
||||
#[cfg(feature = "test-utils")]
|
||||
pub const fn transaction_mut(&mut self) -> &mut Transaction {
|
||||
&mut self.transaction
|
||||
}
|
||||
|
||||
/// Splits the transaction into parts.
|
||||
pub fn into_parts(self) -> (Transaction, Signature, B256) {
|
||||
let hash = *self.hash.get_or_init(|| self.recalculate_hash());
|
||||
@@ -545,8 +434,6 @@ impl alloy_consensus::Transaction for TransactionSigned {
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_signed!(TxLegacy, TxEip2930, TxEip1559, TxEip7702, TxEip4844, TypedTransaction);
|
||||
|
||||
impl From<Signed<Transaction>> for TransactionSigned {
|
||||
fn from(value: Signed<Transaction>) -> Self {
|
||||
let (tx, sig, hash) = value.into_parts();
|
||||
@@ -554,56 +441,6 @@ impl From<Signed<Transaction>> for TransactionSigned {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signed<TxEip4844WithSidecar>> for TransactionSigned {
|
||||
fn from(value: Signed<TxEip4844WithSidecar>) -> Self {
|
||||
let (tx, sig, hash) = value.into_parts();
|
||||
Self::new(tx.tx.into(), sig, hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxEip4844Variant> for Transaction {
|
||||
fn from(variant: TxEip4844Variant) -> Self {
|
||||
match variant {
|
||||
TxEip4844Variant::TxEip4844(tx) => Self::Eip4844(tx),
|
||||
TxEip4844Variant::TxEip4844WithSidecar(tx_with_sidecar) => {
|
||||
Self::Eip4844(tx_with_sidecar.tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signed<TxEip4844Variant>> for TransactionSigned {
|
||||
fn from(value: Signed<TxEip4844Variant>) -> Self {
|
||||
let (tx, sig, hash) = value.into_parts();
|
||||
Self::new(tx.into(), sig, hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxEnvelope> for TransactionSigned {
|
||||
fn from(value: TxEnvelope) -> Self {
|
||||
match value {
|
||||
TxEnvelope::Legacy(tx) => tx.into(),
|
||||
TxEnvelope::Eip2930(tx) => tx.into(),
|
||||
TxEnvelope::Eip1559(tx) => tx.into(),
|
||||
TxEnvelope::Eip4844(tx) => tx.into(),
|
||||
TxEnvelope::Eip7702(tx) => tx.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransactionSigned> for TxEnvelope {
|
||||
fn from(value: TransactionSigned) -> Self {
|
||||
let (tx, signature, hash) = value.into_parts();
|
||||
match tx {
|
||||
Transaction::Legacy(tx) => Signed::new_unchecked(tx, signature, hash).into(),
|
||||
Transaction::Eip2930(tx) => Signed::new_unchecked(tx, signature, hash).into(),
|
||||
Transaction::Eip1559(tx) => Signed::new_unchecked(tx, signature, hash).into(),
|
||||
Transaction::Eip4844(tx) => Signed::new_unchecked(tx, signature, hash).into(),
|
||||
Transaction::Eip7702(tx) => Signed::new_unchecked(tx, signature, hash).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransactionSigned> for EthereumTxEnvelope<TxEip4844> {
|
||||
fn from(value: TransactionSigned) -> Self {
|
||||
let (tx, signature, hash) = value.into_parts();
|
||||
@@ -617,13 +454,6 @@ impl From<TransactionSigned> for EthereumTxEnvelope<TxEip4844> {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransactionSigned> for Signed<Transaction> {
|
||||
fn from(value: TransactionSigned) -> Self {
|
||||
let (tx, sig, hash) = value.into_parts();
|
||||
Self::new_unchecked(tx, sig, hash)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> arbitrary::Arbitrary<'a> for TransactionSigned {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
@@ -810,105 +640,6 @@ impl reth_codecs::Compact for TransactionSigned {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRecoveredTx<TransactionSigned> for TxEnv {
|
||||
fn from_recovered_tx(tx: &TransactionSigned, sender: Address) -> Self {
|
||||
match tx.as_ref() {
|
||||
Transaction::Legacy(tx) => Self {
|
||||
gas_limit: tx.gas_limit,
|
||||
gas_price: tx.gas_price,
|
||||
gas_priority_fee: None,
|
||||
kind: tx.to,
|
||||
value: tx.value,
|
||||
data: tx.input.clone(),
|
||||
chain_id: tx.chain_id,
|
||||
nonce: tx.nonce,
|
||||
access_list: Default::default(),
|
||||
blob_hashes: Default::default(),
|
||||
max_fee_per_blob_gas: Default::default(),
|
||||
authorization_list: Default::default(),
|
||||
tx_type: 0,
|
||||
caller: sender,
|
||||
},
|
||||
Transaction::Eip2930(tx) => Self {
|
||||
gas_limit: tx.gas_limit,
|
||||
gas_price: tx.gas_price,
|
||||
gas_priority_fee: None,
|
||||
kind: tx.to,
|
||||
value: tx.value,
|
||||
data: tx.input.clone(),
|
||||
chain_id: Some(tx.chain_id),
|
||||
nonce: tx.nonce,
|
||||
access_list: tx.access_list.clone(),
|
||||
blob_hashes: Default::default(),
|
||||
max_fee_per_blob_gas: Default::default(),
|
||||
authorization_list: Default::default(),
|
||||
tx_type: 1,
|
||||
caller: sender,
|
||||
},
|
||||
Transaction::Eip1559(tx) => Self {
|
||||
gas_limit: tx.gas_limit,
|
||||
gas_price: tx.max_fee_per_gas,
|
||||
gas_priority_fee: Some(tx.max_priority_fee_per_gas),
|
||||
kind: tx.to,
|
||||
value: tx.value,
|
||||
data: tx.input.clone(),
|
||||
chain_id: Some(tx.chain_id),
|
||||
nonce: tx.nonce,
|
||||
access_list: tx.access_list.clone(),
|
||||
blob_hashes: Default::default(),
|
||||
max_fee_per_blob_gas: Default::default(),
|
||||
authorization_list: Default::default(),
|
||||
tx_type: 2,
|
||||
caller: sender,
|
||||
},
|
||||
Transaction::Eip4844(tx) => Self {
|
||||
gas_limit: tx.gas_limit,
|
||||
gas_price: tx.max_fee_per_gas,
|
||||
gas_priority_fee: Some(tx.max_priority_fee_per_gas),
|
||||
kind: TxKind::Call(tx.to),
|
||||
value: tx.value,
|
||||
data: tx.input.clone(),
|
||||
chain_id: Some(tx.chain_id),
|
||||
nonce: tx.nonce,
|
||||
access_list: tx.access_list.clone(),
|
||||
blob_hashes: tx.blob_versioned_hashes.clone(),
|
||||
max_fee_per_blob_gas: tx.max_fee_per_blob_gas,
|
||||
authorization_list: Default::default(),
|
||||
tx_type: 3,
|
||||
caller: sender,
|
||||
},
|
||||
Transaction::Eip7702(tx) => Self {
|
||||
gas_limit: tx.gas_limit,
|
||||
gas_price: tx.max_fee_per_gas,
|
||||
gas_priority_fee: Some(tx.max_priority_fee_per_gas),
|
||||
kind: TxKind::Call(tx.to),
|
||||
value: tx.value,
|
||||
data: tx.input.clone(),
|
||||
chain_id: Some(tx.chain_id),
|
||||
nonce: tx.nonce,
|
||||
access_list: tx.access_list.clone(),
|
||||
blob_hashes: Default::default(),
|
||||
max_fee_per_blob_gas: Default::default(),
|
||||
authorization_list: tx.authorization_list.clone(),
|
||||
tx_type: 4,
|
||||
caller: sender,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromTxWithEncoded<TransactionSigned> for TxEnv {
|
||||
fn from_encoded_tx(tx: &TransactionSigned, sender: Address, encoded: Bytes) -> Self {
|
||||
match &tx.transaction {
|
||||
Transaction::Legacy(tx) => Self::from_encoded_tx(tx, sender, encoded),
|
||||
Transaction::Eip2930(tx) => Self::from_encoded_tx(tx, sender, encoded),
|
||||
Transaction::Eip1559(tx) => Self::from_encoded_tx(tx, sender, encoded),
|
||||
Transaction::Eip4844(tx) => Self::from_encoded_tx(tx, sender, encoded),
|
||||
Transaction::Eip7702(tx) => Self::from_encoded_tx(tx, sender, encoded),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SignedTransaction for TransactionSigned {
|
||||
fn tx_hash(&self) -> &TxHash {
|
||||
self.hash.get_or_init(|| self.recalculate_hash())
|
||||
@@ -929,222 +660,13 @@ impl SignedTransaction for TransactionSigned {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<TransactionSigned> for PooledTransaction {
|
||||
type Error = TransactionConversionError;
|
||||
|
||||
fn try_from(tx: TransactionSigned) -> Result<Self, Self::Error> {
|
||||
let hash = *tx.tx_hash();
|
||||
match tx {
|
||||
TransactionSigned { transaction: Transaction::Legacy(tx), signature, .. } => {
|
||||
Ok(Self::Legacy(Signed::new_unchecked(tx, signature, hash)))
|
||||
}
|
||||
TransactionSigned { transaction: Transaction::Eip2930(tx), signature, .. } => {
|
||||
Ok(Self::Eip2930(Signed::new_unchecked(tx, signature, hash)))
|
||||
}
|
||||
TransactionSigned { transaction: Transaction::Eip1559(tx), signature, .. } => {
|
||||
Ok(Self::Eip1559(Signed::new_unchecked(tx, signature, hash)))
|
||||
}
|
||||
TransactionSigned { transaction: Transaction::Eip7702(tx), signature, .. } => {
|
||||
Ok(Self::Eip7702(Signed::new_unchecked(tx, signature, hash)))
|
||||
}
|
||||
// Not supported because missing blob sidecar
|
||||
TransactionSigned { transaction: Transaction::Eip4844(_), .. } => {
|
||||
Err(TransactionConversionError::UnsupportedForP2P)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PooledTransaction> for TransactionSigned {
|
||||
fn from(value: PooledTransaction) -> Self {
|
||||
match value {
|
||||
PooledTransaction::Legacy(tx) => tx.into(),
|
||||
PooledTransaction::Eip2930(tx) => tx.into(),
|
||||
PooledTransaction::Eip1559(tx) => tx.into(),
|
||||
PooledTransaction::Eip7702(tx) => tx.into(),
|
||||
PooledTransaction::Eip4844(tx) => {
|
||||
let (tx, signature, hash) = tx.into_parts();
|
||||
Signed::new_unchecked(tx.tx, signature, hash).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bincode-compatible transaction type serde implementations.
|
||||
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
|
||||
pub(super) mod serde_bincode_compat {
|
||||
use alloc::borrow::Cow;
|
||||
use alloy_consensus::{
|
||||
transaction::serde_bincode_compat::{TxEip1559, TxEip2930, TxEip7702, TxLegacy},
|
||||
TxEip4844,
|
||||
};
|
||||
use alloy_primitives::{Signature, TxHash};
|
||||
use reth_primitives_traits::{serde_bincode_compat::SerdeBincodeCompat, SignedTransaction};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_with::{DeserializeAs, SerializeAs};
|
||||
|
||||
/// Bincode-compatible [`super::Transaction`] serde implementation.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[expect(missing_docs)]
|
||||
pub enum Transaction<'a> {
|
||||
Legacy(TxLegacy<'a>),
|
||||
Eip2930(TxEip2930<'a>),
|
||||
Eip1559(TxEip1559<'a>),
|
||||
Eip4844(Cow<'a, TxEip4844>),
|
||||
Eip7702(TxEip7702<'a>),
|
||||
}
|
||||
|
||||
impl<'a> From<&'a super::Transaction> for Transaction<'a> {
|
||||
fn from(value: &'a super::Transaction) -> Self {
|
||||
match value {
|
||||
super::Transaction::Legacy(tx) => Self::Legacy(TxLegacy::from(tx)),
|
||||
super::Transaction::Eip2930(tx) => Self::Eip2930(TxEip2930::from(tx)),
|
||||
super::Transaction::Eip1559(tx) => Self::Eip1559(TxEip1559::from(tx)),
|
||||
super::Transaction::Eip4844(tx) => Self::Eip4844(Cow::Borrowed(tx)),
|
||||
super::Transaction::Eip7702(tx) => Self::Eip7702(TxEip7702::from(tx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Transaction<'a>> for super::Transaction {
|
||||
fn from(value: Transaction<'a>) -> Self {
|
||||
match value {
|
||||
Transaction::Legacy(tx) => Self::Legacy(tx.into()),
|
||||
Transaction::Eip2930(tx) => Self::Eip2930(tx.into()),
|
||||
Transaction::Eip1559(tx) => Self::Eip1559(tx.into()),
|
||||
Transaction::Eip4844(tx) => Self::Eip4844(tx.into_owned()),
|
||||
Transaction::Eip7702(tx) => Self::Eip7702(tx.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bincode-compatible [`super::TransactionSigned`] serde implementation.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct TransactionSigned<'a> {
|
||||
hash: TxHash,
|
||||
signature: Signature,
|
||||
transaction: Transaction<'a>,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a super::TransactionSigned> for TransactionSigned<'a> {
|
||||
fn from(value: &'a super::TransactionSigned) -> Self {
|
||||
Self {
|
||||
hash: *value.tx_hash(),
|
||||
signature: value.signature,
|
||||
transaction: Transaction::from(&value.transaction),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<TransactionSigned<'a>> for super::TransactionSigned {
|
||||
fn from(value: TransactionSigned<'a>) -> Self {
|
||||
Self {
|
||||
hash: value.hash.into(),
|
||||
signature: value.signature,
|
||||
transaction: value.transaction.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SerializeAs<super::TransactionSigned> for TransactionSigned<'_> {
|
||||
fn serialize_as<S>(
|
||||
source: &super::TransactionSigned,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
TransactionSigned::from(source).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> DeserializeAs<'de, super::TransactionSigned> for TransactionSigned<'de> {
|
||||
fn deserialize_as<D>(deserializer: D) -> Result<super::TransactionSigned, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
TransactionSigned::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl SerdeBincodeCompat for super::TransactionSigned {
|
||||
type BincodeRepr<'a> = TransactionSigned<'a>;
|
||||
|
||||
fn as_repr(&self) -> Self::BincodeRepr<'_> {
|
||||
self.into()
|
||||
}
|
||||
|
||||
fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
|
||||
repr.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{serde_bincode_compat, Transaction, TransactionSigned};
|
||||
use arbitrary::Arbitrary;
|
||||
use rand::Rng;
|
||||
use reth_testing_utils::generators;
|
||||
|
||||
#[test]
|
||||
fn test_transaction_bincode_roundtrip() {
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
struct Data<'a> {
|
||||
transaction: serde_bincode_compat::Transaction<'a>,
|
||||
}
|
||||
|
||||
let mut bytes = [0u8; 1024];
|
||||
generators::rng().fill(bytes.as_mut_slice());
|
||||
let tx = Transaction::arbitrary(&mut arbitrary::Unstructured::new(&bytes)).unwrap();
|
||||
let data = Data { transaction: (&tx).into() };
|
||||
|
||||
let encoded = bincode::serialize(&data).unwrap();
|
||||
let decoded: Data<'_> = bincode::deserialize(&encoded).unwrap();
|
||||
assert_eq!(tx, decoded.transaction.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_signed_bincode_roundtrip() {
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
struct Data<'a> {
|
||||
transaction: serde_bincode_compat::TransactionSigned<'a>,
|
||||
}
|
||||
|
||||
let mut bytes = [0u8; 1024];
|
||||
generators::rng().fill(bytes.as_mut_slice());
|
||||
let tx =
|
||||
TransactionSigned::arbitrary(&mut arbitrary::Unstructured::new(&bytes)).unwrap();
|
||||
let data = Data { transaction: (&tx).into() };
|
||||
|
||||
let encoded = bincode::serialize(&data).unwrap();
|
||||
let decoded: Data<'_> = bincode::deserialize(&encoded).unwrap();
|
||||
assert_eq!(tx, decoded.transaction.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloy_consensus::{
|
||||
constants::LEGACY_TX_TYPE_ID, Block, EthereumTxEnvelope, Transaction as _, TxEip1559,
|
||||
TxLegacy,
|
||||
};
|
||||
use alloy_eips::{
|
||||
eip2718::{Decodable2718, Encodable2718},
|
||||
eip7702::constants::SECP256K1N_HALF,
|
||||
};
|
||||
use alloy_primitives::{
|
||||
address, b256, bytes, hex, Address, Bytes, Signature, TxKind, B256, U256,
|
||||
};
|
||||
use alloy_rlp::{Decodable, Encodable, Error as RlpError};
|
||||
use alloy_consensus::EthereumTxEnvelope;
|
||||
use proptest::proptest;
|
||||
use proptest_arbitrary_interop::arb;
|
||||
use reth_codecs::Compact;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use std::str::FromStr;
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
@@ -1201,398 +723,4 @@ mod tests {
|
||||
assert_eq!(actual_tx, expected_tx);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eip_2_reject_high_s_value() {
|
||||
// This pre-homestead transaction has a high `s` value and should be rejected by the
|
||||
// `recover_signer` method:
|
||||
// https://etherscan.io/getRawTx?tx=0x9e6e19637bb625a8ff3d052b7c2fe57dc78c55a15d258d77c43d5a9c160b0384
|
||||
//
|
||||
// Block number: 46170
|
||||
let raw_tx = hex!("f86d8085746a52880082520894c93f2250589a6563f5359051c1ea25746549f0d889208686e75e903bc000801ba034b6fdc33ea520e8123cf5ac4a9ff476f639cab68980cd9366ccae7aef437ea0a0e517caa5f50e27ca0d1e9a92c503b4ccb039680c6d9d0c71203ed611ea4feb33");
|
||||
let tx = TransactionSigned::decode_2718(&mut &raw_tx[..]).unwrap();
|
||||
let signature = &tx.signature;
|
||||
|
||||
// make sure we know it's greater than SECP256K1N_HALF
|
||||
assert!(signature.s() > SECP256K1N_HALF);
|
||||
|
||||
// recover signer, expect failure
|
||||
let hash = *tx.tx_hash();
|
||||
assert!(recover_signer(signature, hash).is_err());
|
||||
|
||||
// use unchecked, ensure it succeeds (the signature is valid if not for EIP-2)
|
||||
assert!(recover_signer_unchecked(signature, hash).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_decode_raw_block() {
|
||||
let bytes = hex!("f90288f90218a0fe21bb173f43067a9f90cfc59bbb6830a7a2929b5de4a61f372a9db28e87f9aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a061effbbcca94f0d3e02e5bd22e986ad57142acabf0cb3d129a6ad8d0f8752e94a0d911c25e97e27898680d242b7780b6faef30995c355a2d5de92e6b9a7212ad3aa0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008003834c4b408252081e80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000842806be9da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421f869f86702842806be9e82520894658bdf435d810c91414ec09147daa6db624063798203e880820a95a040ce7918eeb045ebf8c8b1887ca139d076bda00fa828a07881d442a72626c42da0156576a68e456e295e4c9cf67cf9f53151f329438916e0f24fc69d6bbb7fbacfc0c0");
|
||||
let bytes_buf = &mut bytes.as_ref();
|
||||
let block = Block::<TransactionSigned>::decode(bytes_buf).unwrap();
|
||||
let mut encoded_buf = Vec::with_capacity(bytes.len());
|
||||
block.encode(&mut encoded_buf);
|
||||
assert_eq!(bytes[..], encoded_buf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_block_rlp() {
|
||||
let body = alloy_consensus::BlockBody::<TransactionSigned>::default();
|
||||
let mut buf = Vec::new();
|
||||
body.encode(&mut buf);
|
||||
let decoded = alloy_consensus::BlockBody::decode(&mut buf.as_slice()).unwrap();
|
||||
assert_eq!(body, decoded);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_empty_typed_tx() {
|
||||
let input = [0x80u8];
|
||||
let res = TransactionSigned::decode(&mut &input[..]).unwrap_err();
|
||||
assert_eq!(RlpError::InputTooShort, res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_kind_encoding_sanity() {
|
||||
// check the 0x80 encoding for Create
|
||||
let mut buf = Vec::new();
|
||||
TxKind::Create.encode(&mut buf);
|
||||
assert_eq!(buf, vec![0x80]);
|
||||
|
||||
// check decoding
|
||||
let buf = [0x80];
|
||||
let decoded = TxKind::decode(&mut &buf[..]).unwrap();
|
||||
assert_eq!(decoded, TxKind::Create);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_create_goerli() {
|
||||
// test that an example create tx from goerli decodes properly
|
||||
let tx_bytes = hex!("b901f202f901ee05228459682f008459682f11830209bf8080b90195608060405234801561001057600080fd5b50610175806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630c49c36c14610030575b600080fd5b61003861004e565b604051610045919061011d565b60405180910390f35b60606020600052600f6020527f68656c6c6f2073746174656d696e64000000000000000000000000000000000060405260406000f35b600081519050919050565b600082825260208201905092915050565b60005b838110156100be5780820151818401526020810190506100a3565b838111156100cd576000848401525b50505050565b6000601f19601f8301169050919050565b60006100ef82610084565b6100f9818561008f565b93506101098185602086016100a0565b610112816100d3565b840191505092915050565b6000602082019050818103600083015261013781846100e4565b90509291505056fea264697066735822122051449585839a4ea5ac23cae4552ef8a96b64ff59d0668f76bfac3796b2bdbb3664736f6c63430008090033c080a0136ebffaa8fc8b9fda9124de9ccb0b1f64e90fbd44251b4c4ac2501e60b104f9a07eb2999eec6d185ef57e91ed099afb0a926c5b536f0155dd67e537c7476e1471");
|
||||
|
||||
let decoded = TransactionSigned::decode(&mut &tx_bytes[..]).unwrap();
|
||||
assert_eq!(tx_bytes.len(), decoded.length());
|
||||
assert_eq!(tx_bytes, &alloy_rlp::encode(decoded)[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_recover_mainnet_tx() {
|
||||
// random mainnet tx <https://etherscan.io/tx/0x86718885c4b4218c6af87d3d0b0d83e3cc465df2a05c048aa4db9f1a6f9de91f>
|
||||
let tx_bytes = hex!("02f872018307910d808507204d2cb1827d0094388c818ca8b9251b393131c08a736a67ccb19297880320d04823e2701c80c001a0cf024f4815304df2867a1a74e9d2707b6abda0337d2d54a4438d453f4160f190a07ac0e6b3bc9395b5b9c8b9e6d77204a236577a5b18467b9175c01de4faa208d9");
|
||||
|
||||
let decoded = TransactionSigned::decode_2718(&mut &tx_bytes[..]).unwrap();
|
||||
assert_eq!(
|
||||
decoded.recover_signer().unwrap(),
|
||||
address!("0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Test vector from https://sepolia.etherscan.io/tx/0x9a22ccb0029bc8b0ddd073be1a1d923b7ae2b2ea52100bae0db4424f9107e9c0
|
||||
// Blobscan: https://sepolia.blobscan.com/tx/0x9a22ccb0029bc8b0ddd073be1a1d923b7ae2b2ea52100bae0db4424f9107e9c0
|
||||
fn test_decode_recover_sepolia_4844_tx() {
|
||||
use alloy_primitives::{address, b256};
|
||||
|
||||
// https://sepolia.etherscan.io/getRawTx?tx=0x9a22ccb0029bc8b0ddd073be1a1d923b7ae2b2ea52100bae0db4424f9107e9c0
|
||||
let raw_tx = alloy_primitives::hex::decode("0x03f9011d83aa36a7820fa28477359400852e90edd0008252089411e9ca82a3a762b4b5bd264d4173a242e7a770648080c08504a817c800f8a5a0012ec3d6f66766bedb002a190126b3549fce0047de0d4c25cffce0dc1c57921aa00152d8e24762ff22b1cfd9f8c0683786a7ca63ba49973818b3d1e9512cd2cec4a0013b98c6c83e066d5b14af2b85199e3d4fc7d1e778dd53130d180f5077e2d1c7a001148b495d6e859114e670ca54fb6e2657f0cbae5b08063605093a4b3dc9f8f1a0011ac212f13c5dff2b2c6b600a79635103d6f580a4221079951181b25c7e654901a0c8de4cced43169f9aa3d36506363b2d2c44f6c49fc1fd91ea114c86f3757077ea01e11fdd0d1934eda0492606ee0bb80a7bf8f35cc5f86ec60fe5031ba48bfd544").unwrap();
|
||||
let decoded = TransactionSigned::decode_2718(&mut raw_tx.as_slice()).unwrap();
|
||||
assert!(alloy_consensus::Typed2718::is_eip4844(&decoded));
|
||||
|
||||
assert_eq!(
|
||||
decoded.recover_signer().ok(),
|
||||
Some(address!("0xA83C816D4f9b2783761a22BA6FADB0eB0606D7B2"))
|
||||
);
|
||||
|
||||
let tx = decoded.transaction;
|
||||
|
||||
assert_eq!(tx.to(), Some(address!("0x11E9CA82A3a762b4B5bd264d4173a242e7a77064")));
|
||||
|
||||
assert_eq!(
|
||||
tx.blob_versioned_hashes(),
|
||||
Some(
|
||||
&[
|
||||
b256!("0x012ec3d6f66766bedb002a190126b3549fce0047de0d4c25cffce0dc1c57921a"),
|
||||
b256!("0x0152d8e24762ff22b1cfd9f8c0683786a7ca63ba49973818b3d1e9512cd2cec4"),
|
||||
b256!("0x013b98c6c83e066d5b14af2b85199e3d4fc7d1e778dd53130d180f5077e2d1c7"),
|
||||
b256!("0x01148b495d6e859114e670ca54fb6e2657f0cbae5b08063605093a4b3dc9f8f1"),
|
||||
b256!("0x011ac212f13c5dff2b2c6b600a79635103d6f580a4221079951181b25c7e6549"),
|
||||
][..]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_transaction_consumes_buffer() {
|
||||
let bytes = &mut &hex!("b87502f872041a8459682f008459682f0d8252089461815774383099e24810ab832a5b2a5425c154d58829a2241af62c000080c001a059e6b67f48fb32e7e570dfb11e042b5ad2e55e3ce3ce9cd989c7e06e07feeafda0016b83f4f980694ed2eee4d10667242b1f40dc406901b34125b008d334d47469")[..];
|
||||
let _transaction_res = TransactionSigned::decode(bytes).unwrap();
|
||||
assert_eq!(
|
||||
bytes.len(),
|
||||
0,
|
||||
"did not consume all bytes in the buffer, {:?} remaining",
|
||||
bytes.len()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_multiple_network_txs() {
|
||||
let bytes = hex!("f86b02843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba00eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5aea03a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18");
|
||||
let transaction = Transaction::Legacy(TxLegacy {
|
||||
chain_id: Some(4u64),
|
||||
nonce: 2,
|
||||
gas_price: 1000000000,
|
||||
gas_limit: 100000,
|
||||
to: Address::from_str("d3e8763675e4c425df46cc3b5c0f6cbdac396046").unwrap().into(),
|
||||
value: U256::from(1000000000000000u64),
|
||||
input: Bytes::default(),
|
||||
});
|
||||
let signature = Signature::new(
|
||||
U256::from_str("0xeb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae")
|
||||
.unwrap(),
|
||||
U256::from_str("0x3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18")
|
||||
.unwrap(),
|
||||
false,
|
||||
);
|
||||
let hash = b256!("0xa517b206d2223278f860ea017d3626cacad4f52ff51030dc9a96b432f17f8d34");
|
||||
test_decode_and_encode(&bytes, transaction, signature, Some(hash));
|
||||
|
||||
let bytes = hex!("f86b01843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac3960468702769bb01b2a00802ba0e24d8bd32ad906d6f8b8d7741e08d1959df021698b19ee232feba15361587d0aa05406ad177223213df262cb66ccbb2f46bfdccfdfbbb5ffdda9e2c02d977631da");
|
||||
let transaction = Transaction::Legacy(TxLegacy {
|
||||
chain_id: Some(4),
|
||||
nonce: 1u64,
|
||||
gas_price: 1000000000,
|
||||
gas_limit: 100000,
|
||||
to: Address::from_slice(&hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046")[..]).into(),
|
||||
value: U256::from(693361000000000u64),
|
||||
input: Default::default(),
|
||||
});
|
||||
let signature = Signature::new(
|
||||
U256::from_str("0xe24d8bd32ad906d6f8b8d7741e08d1959df021698b19ee232feba15361587d0a")
|
||||
.unwrap(),
|
||||
U256::from_str("0x5406ad177223213df262cb66ccbb2f46bfdccfdfbbb5ffdda9e2c02d977631da")
|
||||
.unwrap(),
|
||||
false,
|
||||
);
|
||||
test_decode_and_encode(&bytes, transaction, signature, None);
|
||||
|
||||
let bytes = hex!("f86b0384773594008398968094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba0ce6834447c0a4193c40382e6c57ae33b241379c5418caac9cdc18d786fd12071a03ca3ae86580e94550d7c071e3a02eadb5a77830947c9225165cf9100901bee88");
|
||||
let transaction = Transaction::Legacy(TxLegacy {
|
||||
chain_id: Some(4),
|
||||
nonce: 3,
|
||||
gas_price: 2000000000,
|
||||
gas_limit: 10000000,
|
||||
to: Address::from_slice(&hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046")[..]).into(),
|
||||
value: U256::from(1000000000000000u64),
|
||||
input: Bytes::default(),
|
||||
});
|
||||
let signature = Signature::new(
|
||||
U256::from_str("0xce6834447c0a4193c40382e6c57ae33b241379c5418caac9cdc18d786fd12071")
|
||||
.unwrap(),
|
||||
U256::from_str("0x3ca3ae86580e94550d7c071e3a02eadb5a77830947c9225165cf9100901bee88")
|
||||
.unwrap(),
|
||||
false,
|
||||
);
|
||||
test_decode_and_encode(&bytes, transaction, signature, None);
|
||||
|
||||
let bytes = hex!("b87502f872041a8459682f008459682f0d8252089461815774383099e24810ab832a5b2a5425c154d58829a2241af62c000080c001a059e6b67f48fb32e7e570dfb11e042b5ad2e55e3ce3ce9cd989c7e06e07feeafda0016b83f4f980694ed2eee4d10667242b1f40dc406901b34125b008d334d47469");
|
||||
let transaction = Transaction::Eip1559(TxEip1559 {
|
||||
chain_id: 4,
|
||||
nonce: 26,
|
||||
max_priority_fee_per_gas: 1500000000,
|
||||
max_fee_per_gas: 1500000013,
|
||||
gas_limit: 21_000,
|
||||
to: Address::from_slice(&hex!("61815774383099e24810ab832a5b2a5425c154d5")[..]).into(),
|
||||
value: U256::from(3000000000000000000u64),
|
||||
input: Default::default(),
|
||||
access_list: Default::default(),
|
||||
});
|
||||
let signature = Signature::new(
|
||||
U256::from_str("0x59e6b67f48fb32e7e570dfb11e042b5ad2e55e3ce3ce9cd989c7e06e07feeafd")
|
||||
.unwrap(),
|
||||
U256::from_str("0x016b83f4f980694ed2eee4d10667242b1f40dc406901b34125b008d334d47469")
|
||||
.unwrap(),
|
||||
true,
|
||||
);
|
||||
test_decode_and_encode(&bytes, transaction, signature, None);
|
||||
|
||||
let bytes = hex!("f8650f84832156008287fb94cf7f9e66af820a19257a2108375b180b0ec491678204d2802ca035b7bfeb9ad9ece2cbafaaf8e202e706b4cfaeb233f46198f00b44d4a566a981a0612638fb29427ca33b9a3be2a0a561beecfe0269655be160d35e72d366a6a860");
|
||||
let transaction = Transaction::Legacy(TxLegacy {
|
||||
chain_id: Some(4),
|
||||
nonce: 15,
|
||||
gas_price: 2200000000,
|
||||
gas_limit: 34811,
|
||||
to: Address::from_slice(&hex!("cf7f9e66af820a19257a2108375b180b0ec49167")[..]).into(),
|
||||
value: U256::from(1234),
|
||||
input: Bytes::default(),
|
||||
});
|
||||
let signature = Signature::new(
|
||||
U256::from_str("0x35b7bfeb9ad9ece2cbafaaf8e202e706b4cfaeb233f46198f00b44d4a566a981")
|
||||
.unwrap(),
|
||||
U256::from_str("0x612638fb29427ca33b9a3be2a0a561beecfe0269655be160d35e72d366a6a860")
|
||||
.unwrap(),
|
||||
true,
|
||||
);
|
||||
test_decode_and_encode(&bytes, transaction, signature, None);
|
||||
}
|
||||
|
||||
fn test_decode_and_encode(
|
||||
bytes: &[u8],
|
||||
transaction: Transaction,
|
||||
signature: Signature,
|
||||
hash: Option<B256>,
|
||||
) {
|
||||
let expected = TransactionSigned::new_unhashed(transaction, signature);
|
||||
if let Some(hash) = hash {
|
||||
assert_eq!(hash, *expected.tx_hash());
|
||||
}
|
||||
assert_eq!(bytes.len(), expected.length());
|
||||
|
||||
let decoded = TransactionSigned::decode(&mut &bytes[..]).unwrap();
|
||||
assert_eq!(expected, decoded);
|
||||
assert_eq!(bytes, &alloy_rlp::encode(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_raw_tx_and_recover_signer() {
|
||||
use alloy_primitives::hex_literal::hex;
|
||||
// transaction is from ropsten
|
||||
|
||||
let hash: B256 =
|
||||
hex!("559fb34c4a7f115db26cbf8505389475caaab3df45f5c7a0faa4abfa3835306c").into();
|
||||
let signer: Address = hex!("641c5d790f862a58ec7abcfd644c0442e9c201b3").into();
|
||||
let raw = hex!("f88b8212b085028fa6ae00830f424094aad593da0c8116ef7d2d594dd6a63241bccfc26c80a48318b64b000000000000000000000000641c5d790f862a58ec7abcfd644c0442e9c201b32aa0a6ef9e170bca5ffb7ac05433b13b7043de667fbb0b4a5e45d3b54fb2d6efcc63a0037ec2c05c3d60c5f5f78244ce0a3859e3a18a36c61efb061b383507d3ce19d2");
|
||||
|
||||
let mut pointer = raw.as_ref();
|
||||
let tx = TransactionSigned::decode(&mut pointer).unwrap();
|
||||
assert_eq!(*tx.tx_hash(), hash, "Expected same hash");
|
||||
let recovered = tx.recover_signer().expect("Recovering signer should pass");
|
||||
assert_eq!(recovered, signer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_envelop_encode() {
|
||||
// random tx: <https://etherscan.io/getRawTx?tx=0x9448608d36e721ef403c53b00546068a6474d6cbab6816c3926de449898e7bce>
|
||||
let input = hex!("02f871018302a90f808504890aef60826b6c94ddf4c5025d1a5742cf12f74eec246d4432c295e487e09c3bbcc12b2b80c080a0f21a4eacd0bf8fea9c5105c543be5a1d8c796516875710fafafdf16d16d8ee23a001280915021bb446d1973501a67f93d2b38894a514b976e7b46dc2fe54598d76");
|
||||
let decoded = TransactionSigned::decode(&mut &input[..]).unwrap();
|
||||
|
||||
let encoded = decoded.encoded_2718();
|
||||
assert_eq!(encoded[..], input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_envelop_decode() {
|
||||
// random tx: <https://etherscan.io/getRawTx?tx=0x9448608d36e721ef403c53b00546068a6474d6cbab6816c3926de449898e7bce>
|
||||
let input = bytes!("02f871018302a90f808504890aef60826b6c94ddf4c5025d1a5742cf12f74eec246d4432c295e487e09c3bbcc12b2b80c080a0f21a4eacd0bf8fea9c5105c543be5a1d8c796516875710fafafdf16d16d8ee23a001280915021bb446d1973501a67f93d2b38894a514b976e7b46dc2fe54598d76");
|
||||
let decoded = TransactionSigned::decode_2718(&mut input.as_ref()).unwrap();
|
||||
|
||||
let encoded = decoded.encoded_2718();
|
||||
assert_eq!(encoded, input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_tx() {
|
||||
// some random transactions pulled from hive tests
|
||||
let data = hex!("b86f02f86c0705843b9aca008506fc23ac00830124f89400000000000000000000000000000000000003160180c001a00293c713e2f1eab91c366621ff2f867e05ad7e99d4aa5d069aafeb9e1e8c9b6aa05ec6c0605ff20b57c90a6484ec3b0509e5923733d06f9b69bee9a2dabe4f1352");
|
||||
let tx = TransactionSigned::decode(&mut data.as_slice()).unwrap();
|
||||
let mut b = Vec::with_capacity(data.len());
|
||||
tx.encode(&mut b);
|
||||
assert_eq!(data.as_slice(), b.as_slice());
|
||||
|
||||
let data = hex!("f865048506fc23ac00830124f8940000000000000000000000000000000000000316018032a06b8fdfdcb84790816b7af85b19305f493665fe8b4e7c51ffdd7cc144cd776a60a028a09ab55def7b8d6602ba1c97a0ebbafe64ffc9c8e89520cec97a8edfb2ebe9");
|
||||
let tx = TransactionSigned::decode(&mut data.as_slice()).unwrap();
|
||||
let mut b = Vec::with_capacity(data.len());
|
||||
tx.encode(&mut b);
|
||||
assert_eq!(data.as_slice(), b.as_slice());
|
||||
}
|
||||
|
||||
// <https://etherscan.io/tx/0x280cde7cdefe4b188750e76c888f13bd05ce9a4d7767730feefe8a0e50ca6fc4>
|
||||
#[test]
|
||||
fn recover_legacy_singer() {
|
||||
let data = hex!("f9015482078b8505d21dba0083022ef1947a250d5630b4cf539739df2c5dacb4c659f2488d880c46549a521b13d8b8e47ff36ab50000000000000000000000000000000000000000000066ab5a608bd00a23f2fe000000000000000000000000000000000000000000000000000000000000008000000000000000000000000048c04ed5691981c42154c6167398f95e8f38a7ff00000000000000000000000000000000000000000000000000000000632ceac70000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006c6ee5e31d828de241282b9606c8e98ea48526e225a0c9077369501641a92ef7399ff81c21639ed4fd8fc69cb793cfa1dbfab342e10aa0615facb2f1bcf3274a354cfe384a38d0cc008a11c2dd23a69111bc6930ba27a8");
|
||||
let tx = TransactionSigned::fallback_decode(&mut data.as_slice()).unwrap();
|
||||
assert_eq!(tx.ty(), LEGACY_TX_TYPE_ID);
|
||||
let sender = tx.recover_signer().unwrap();
|
||||
assert_eq!(sender, address!("0xa12e1462d0ceD572f396F58B6E2D03894cD7C8a4"));
|
||||
}
|
||||
|
||||
// <https://github.com/alloy-rs/alloy/issues/141>
|
||||
// <https://etherscan.io/tx/0xce4dc6d7a7549a98ee3b071b67e970879ff51b5b95d1c340bacd80fa1e1aab31>
|
||||
#[test]
|
||||
fn recover_enveloped() {
|
||||
let data = hex!("02f86f0102843b9aca0085029e7822d68298f094d9e1459a7a482635700cbc20bbaf52d495ab9c9680841b55ba3ac080a0c199674fcb29f353693dd779c017823b954b3c69dffa3cd6b2a6ff7888798039a028ca912de909e7e6cdef9cdcaf24c54dd8c1032946dfa1d85c206b32a9064fe8");
|
||||
let tx = TransactionSigned::decode_2718(&mut data.as_slice()).unwrap();
|
||||
let sender = tx.recover_signer().unwrap();
|
||||
assert_eq!(sender, address!("0x001e2b7dE757bA469a57bF6b23d982458a07eFcE"));
|
||||
assert_eq!(tx.to(), Some(address!("0xD9e1459A7A482635700cBc20BBAF52D495Ab9C96")));
|
||||
assert_eq!(tx.input().as_ref(), hex!("1b55ba3a"));
|
||||
let encoded = tx.encoded_2718();
|
||||
assert_eq!(encoded.as_ref(), data.to_vec());
|
||||
}
|
||||
|
||||
// <https://github.com/paradigmxyz/reth/issues/7750>
|
||||
// <https://etherscan.io/tx/0x2084b8144eea4031c2fa7dfe343498c5e665ca85ed17825f2925f0b5b01c36ac>
|
||||
#[test]
|
||||
fn recover_pre_eip2() {
|
||||
let data = hex!("f8ea0c850ba43b7400832dc6c0942935aa0a2d2fbb791622c29eb1c117b65b7a908580b884590528a9000000000000000000000001878ace42092b7f1ae1f28d16c1272b1aa80ca4670000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000d02ab486cedc0000000000000000000000000000000000000000000000000000557fe293cabc08cf1ca05bfaf3fda0a56b49cc78b22125feb5ae6a99d2b4781f00507d8b02c173771c85a0b5da0dbe6c5bc53740d0071fc83eb17ba0f709e49e9ae7df60dee625ef51afc5");
|
||||
let tx = TransactionSigned::decode_2718(&mut data.as_slice()).unwrap();
|
||||
let sender = tx.recover_signer();
|
||||
assert!(sender.is_err());
|
||||
let sender = tx.recover_signer_unchecked().unwrap();
|
||||
|
||||
assert_eq!(sender, address!("0x7e9e359edf0dbacf96a9952fa63092d919b0842b"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transaction_signed_no_hash_zstd_codec() {
|
||||
// will use same signature everywhere.
|
||||
// We don't need signature to match tx, just decoded to the same signature
|
||||
let signature = Signature::new(
|
||||
U256::from_str("0xeb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae")
|
||||
.unwrap(),
|
||||
U256::from_str("0x3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18")
|
||||
.unwrap(),
|
||||
false,
|
||||
);
|
||||
|
||||
let inputs: Vec<Vec<u8>> = vec![
|
||||
vec![],
|
||||
vec![0],
|
||||
vec![255],
|
||||
vec![1u8; 31],
|
||||
vec![255u8; 31],
|
||||
vec![1u8; 32],
|
||||
vec![255u8; 32],
|
||||
vec![1u8; 64],
|
||||
vec![255u8; 64],
|
||||
];
|
||||
|
||||
for input in inputs {
|
||||
let transaction = Transaction::Legacy(TxLegacy {
|
||||
chain_id: Some(4u64),
|
||||
nonce: 2,
|
||||
gas_price: 1000000000,
|
||||
gas_limit: 100000,
|
||||
to: Address::from_str("d3e8763675e4c425df46cc3b5c0f6cbdac396046").unwrap().into(),
|
||||
value: U256::from(1000000000000000u64),
|
||||
input: Bytes::from(input),
|
||||
});
|
||||
|
||||
let tx = TransactionSigned::new_unhashed(transaction, signature);
|
||||
test_transaction_signed_to_from_compact(tx);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_transaction_signed_to_from_compact(tx: TransactionSigned) {
|
||||
// zstd aware `to_compact`
|
||||
let mut buff: Vec<u8> = Vec::new();
|
||||
let written_bytes = tx.to_compact(&mut buff);
|
||||
let (decoded, _) = TransactionSigned::from_compact(&buff, written_bytes);
|
||||
assert_eq!(tx, decoded);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_txs_disallowed_for_eip4844() {
|
||||
let data =
|
||||
[3, 208, 128, 128, 123, 128, 120, 128, 129, 129, 128, 192, 129, 129, 192, 128, 128, 9];
|
||||
let res = TransactionSigned::decode_2718(&mut &data[..]);
|
||||
|
||||
assert!(res.is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ full = [
|
||||
"network",
|
||||
]
|
||||
|
||||
alloy-compat = ["reth-ethereum-primitives/alloy-compat"]
|
||||
cli = ["dep:reth-ethereum-cli"]
|
||||
consensus = [
|
||||
"dep:reth-consensus",
|
||||
|
||||
Binary file not shown.
@@ -9,7 +9,6 @@ use reth_network::{
|
||||
NetworkEvent, NetworkEventListenerProvider, Peers,
|
||||
};
|
||||
use reth_network_api::{events::PeerEvent, PeerKind, PeersInfo};
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::test_utils::{ExtendedAccount, MockEthProvider};
|
||||
use reth_transaction_pool::{test_utils::TransactionGenerator, PoolTransaction, TransactionPool};
|
||||
use std::sync::Arc;
|
||||
@@ -115,7 +114,8 @@ async fn test_tx_propagation_policy_trusted_only() {
|
||||
|
||||
// ensure peer1 now receives the pending txs from peer0
|
||||
let mut buff = Vec::with_capacity(2);
|
||||
peer1_tx_listener.recv_many(&mut buff, 2).await;
|
||||
buff.push(peer1_tx_listener.recv().await.unwrap());
|
||||
buff.push(peer1_tx_listener.recv().await.unwrap());
|
||||
|
||||
assert!(buff.contains(&hash_1));
|
||||
}
|
||||
|
||||
@@ -88,9 +88,7 @@ c-kzg = [
|
||||
"alloy-consensus/kzg",
|
||||
"alloy-eips/kzg",
|
||||
]
|
||||
alloy-compat = [
|
||||
"reth-ethereum-primitives/alloy-compat",
|
||||
]
|
||||
alloy-compat = []
|
||||
test-utils = [
|
||||
"reth-primitives-traits/test-utils",
|
||||
"arbitrary",
|
||||
|
||||
@@ -12,7 +12,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
let raw =hex!("f88b8212b085028fa6ae00830f424094aad593da0c8116ef7d2d594dd6a63241bccfc26c80a48318b64b000000000000000000000000641c5d790f862a58ec7abcfd644c0442e9c201b32aa0a6ef9e170bca5ffb7ac05433b13b7043de667fbb0b4a5e45d3b54fb2d6efcc63a0037ec2c05c3d60c5f5f78244ce0a3859e3a18a36c61efb061b383507d3ce19d2");
|
||||
let mut pointer = raw.as_ref();
|
||||
let tx = TransactionSigned::decode(&mut pointer).unwrap();
|
||||
tx.recover_signer().unwrap();
|
||||
SignedTransaction::recover_signer(&tx).unwrap();
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
//!
|
||||
//! ## Feature Flags
|
||||
//!
|
||||
//! - `alloy-compat`: Adds compatibility conversions for certain alloy types.
|
||||
//! - `arbitrary`: Adds `proptest` and `arbitrary` support for primitive types.
|
||||
//! - `test-utils`: Export utilities for testing
|
||||
//! - `reth-codec`: Enables db codec support for reth types including zstd compression for certain
|
||||
|
||||
@@ -90,7 +90,6 @@ mod tests {
|
||||
Itertools,
|
||||
};
|
||||
use reth_db_api::tables;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::{DatabaseProviderFactory, PruneCheckpointReader};
|
||||
use reth_prune_types::{PruneCheckpoint, PruneMode, PruneProgress, PruneSegment};
|
||||
use reth_stages::test_utils::{StorageKind, TestStageDB};
|
||||
|
||||
@@ -117,7 +117,6 @@ mod tests {
|
||||
Itertools,
|
||||
};
|
||||
use reth_db_api::tables;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::{DatabaseProviderFactory, PruneCheckpointReader};
|
||||
use reth_prune_types::{
|
||||
PruneCheckpoint, PruneInterruptReason, PruneMode, PruneProgress, PruneSegment,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use alloy_consensus::{transaction::TransactionMeta, BlockHeader};
|
||||
use alloy_rpc_types_eth::{BlockId, TransactionReceipt};
|
||||
use reth_chainspec::{ChainSpecProvider, EthChainSpec};
|
||||
use reth_primitives_traits::{BlockBody, SignedTransaction};
|
||||
use reth_primitives_traits::BlockBody;
|
||||
use reth_rpc_eth_api::{
|
||||
helpers::{EthBlocks, LoadBlock, LoadPendingBlock, LoadReceipt, SpawnBlocking},
|
||||
types::RpcTypes,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! L1 `eth` API types.
|
||||
|
||||
use alloy_consensus::{Transaction as _, TxEnvelope};
|
||||
use alloy_consensus::{EthereumTxEnvelope, Transaction as _, TxEnvelope};
|
||||
use alloy_network::{Ethereum, Network};
|
||||
use alloy_primitives::Signature;
|
||||
use alloy_rpc_types::TransactionRequest;
|
||||
@@ -74,7 +74,8 @@ where
|
||||
|
||||
// Create an empty signature for the transaction.
|
||||
let signature = Signature::new(Default::default(), Default::default(), false);
|
||||
Ok(TransactionSigned::new_unhashed(tx.into(), signature))
|
||||
// TODO(mattsse): simplify
|
||||
Ok(EthereumTxEnvelope::new_unhashed(tx, signature).into())
|
||||
}
|
||||
|
||||
fn otterscan_api_truncate_input(tx: &mut Self::Transaction) {
|
||||
|
||||
@@ -220,7 +220,7 @@ mod tests {
|
||||
models::StoredBlockBodyIndices,
|
||||
};
|
||||
use reth_ethereum_primitives::Block;
|
||||
use reth_primitives_traits::{SealedBlock, SignedTransaction};
|
||||
use reth_primitives_traits::SealedBlock;
|
||||
use reth_provider::providers::StaticFileWriter;
|
||||
use reth_testing_utils::generators::{
|
||||
self, random_block_range, random_contract_account_range, BlockRangeParams,
|
||||
|
||||
@@ -45,7 +45,10 @@ use utils::*;
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test_utils::{StorageKind, TestStageDB};
|
||||
use alloy_primitives::{address, hex_literal::hex, keccak256, BlockNumber, B256, U256};
|
||||
use alloy_consensus::{SignableTransaction, TxLegacy};
|
||||
use alloy_primitives::{
|
||||
address, hex_literal::hex, keccak256, BlockNumber, Signature, B256, U256,
|
||||
};
|
||||
use alloy_rlp::Decodable;
|
||||
use reth_chainspec::ChainSpecBuilder;
|
||||
use reth_db::mdbx::{cursor::Cursor, RW};
|
||||
@@ -502,7 +505,7 @@ mod tests {
|
||||
&db,
|
||||
current + 2,
|
||||
Some(PipelineTarget::Unwind(89)),
|
||||
&Default::default(),
|
||||
&TxLegacy::default().into_signed(Signature::test_signature()).into(),
|
||||
);
|
||||
|
||||
// Fill the gap, and ensure no unwind is necessary.
|
||||
@@ -510,7 +513,7 @@ mod tests {
|
||||
&db,
|
||||
current + 1,
|
||||
None,
|
||||
&Default::default(),
|
||||
&TxLegacy::default().into_signed(Signature::test_signature()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ mod tests {
|
||||
};
|
||||
use alloy_primitives::B256;
|
||||
use reth_ethereum_primitives::Block;
|
||||
use reth_primitives_traits::{SealedBlock, SignedTransaction};
|
||||
use reth_primitives_traits::SealedBlock;
|
||||
use reth_provider::{
|
||||
providers::StaticFileWriter, TransactionsProvider, TransactionsProviderExt,
|
||||
};
|
||||
|
||||
@@ -376,7 +376,7 @@ mod tests {
|
||||
use assert_matches::assert_matches;
|
||||
use reth_db_api::cursor::DbCursorRO;
|
||||
use reth_ethereum_primitives::{Block, TransactionSigned};
|
||||
use reth_primitives_traits::{SealedBlock, SignedTransaction};
|
||||
use reth_primitives_traits::SealedBlock;
|
||||
use reth_provider::{
|
||||
providers::StaticFileWriter, BlockBodyIndicesProvider, DatabaseProviderFactory,
|
||||
PruneCheckpointWriter, StaticFileProviderFactory, TransactionsProvider,
|
||||
|
||||
@@ -660,7 +660,6 @@ mod tests {
|
||||
test_utils::{create_test_static_files_dir, ERROR_TEMPDIR},
|
||||
};
|
||||
use reth_db_api::tables;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_prune_types::{PruneMode, PruneModes};
|
||||
use reth_storage_errors::provider::ProviderError;
|
||||
use reth_testing_utils::generators::{self, random_block, random_header, BlockParams};
|
||||
|
||||
@@ -57,8 +57,8 @@ mod tests {
|
||||
use crate::{
|
||||
test_utils::create_test_provider_factory, HeaderProvider, StaticFileProviderFactory,
|
||||
};
|
||||
use alloy_consensus::{Header, Transaction};
|
||||
use alloy_primitives::{BlockHash, TxNumber, B256, U256};
|
||||
use alloy_consensus::{Header, SignableTransaction, Transaction, TxLegacy};
|
||||
use alloy_primitives::{BlockHash, Signature, TxNumber, B256, U256};
|
||||
use rand::seq::SliceRandom;
|
||||
use reth_db::test_utils::create_test_static_files_dir;
|
||||
use reth_db_api::{
|
||||
@@ -315,7 +315,7 @@ mod tests {
|
||||
next_tx_num: &mut u64,
|
||||
) {
|
||||
let mut receipt = Receipt::default();
|
||||
let mut tx = TransactionSigned::default();
|
||||
let mut tx = TxLegacy::default();
|
||||
|
||||
for block in block_range.clone() {
|
||||
writer.increment_block(block).unwrap();
|
||||
@@ -328,7 +328,9 @@ mod tests {
|
||||
writer.append_receipt(*next_tx_num, &receipt).unwrap();
|
||||
} else {
|
||||
// Used as ID for validation
|
||||
tx.transaction_mut().set_nonce(*next_tx_num);
|
||||
tx.nonce = *next_tx_num;
|
||||
let tx: TransactionSigned =
|
||||
tx.clone().into_signed(Signature::test_signature()).into();
|
||||
writer.append_transaction(*next_tx_num, &tx).unwrap();
|
||||
}
|
||||
*next_tx_num += 1;
|
||||
|
||||
@@ -94,7 +94,7 @@ pub(crate) static TEST_BLOCK: LazyLock<SealedBlock<reth_ethereum_primitives::Blo
|
||||
hex!("cf7b274520720b50e6a4c3e5c4d553101f44945396827705518ce17cb7219a42").into(),
|
||||
),
|
||||
BlockBody {
|
||||
transactions: vec![TransactionSigned::new(
|
||||
transactions: vec![TransactionSigned::new_unhashed(
|
||||
Transaction::Legacy(TxLegacy {
|
||||
gas_price: 10,
|
||||
gas_limit: 400_000,
|
||||
@@ -111,8 +111,7 @@ pub(crate) static TEST_BLOCK: LazyLock<SealedBlock<reth_ethereum_primitives::Blo
|
||||
)
|
||||
.unwrap(),
|
||||
false,
|
||||
),
|
||||
b256!("0x3541dd1d17e76adeb25dcf2b0a9b60a1669219502e58dcf26a2beafbfb550397"),
|
||||
)
|
||||
)],
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
@@ -24,7 +24,6 @@ use reth_execution_types::ExecutionOutcome;
|
||||
use reth_node_types::NodeTypes;
|
||||
use reth_primitives_traits::{
|
||||
Account, Bytecode, GotExpected, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader,
|
||||
SignedTransaction,
|
||||
};
|
||||
use reth_prune_types::PruneModes;
|
||||
use reth_stages_types::{StageCheckpoint, StageId};
|
||||
|
||||
@@ -5,9 +5,7 @@ use alloy_primitives::{Address, Bytes, TxKind, B256, U256};
|
||||
use rand::{Rng, RngCore};
|
||||
use reth_chainspec::MAINNET;
|
||||
use reth_ethereum_primitives::{Transaction, TransactionSigned};
|
||||
use reth_primitives_traits::{
|
||||
crypto::secp256k1::sign_message, transaction::signed::SignedTransaction,
|
||||
};
|
||||
use reth_primitives_traits::crypto::secp256k1::sign_message;
|
||||
|
||||
/// A generator for transactions for testing purposes.
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -13,8 +13,8 @@ use alloy_consensus::{
|
||||
LEGACY_TX_TYPE_ID,
|
||||
},
|
||||
transaction::PooledTransaction,
|
||||
EthereumTxEnvelope, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEip7702, TxEnvelope,
|
||||
TxLegacy, TxType, Typed2718,
|
||||
EthereumTxEnvelope, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEip7702,
|
||||
TxEnvelope, TxLegacy, TxType, Typed2718,
|
||||
};
|
||||
use alloy_eips::{
|
||||
eip1559::MIN_PROTOCOL_BASE_FEE,
|
||||
@@ -27,10 +27,11 @@ use paste::paste;
|
||||
use rand::{distr::Uniform, prelude::Distribution};
|
||||
use reth_ethereum_primitives::{Transaction, TransactionSigned};
|
||||
use reth_primitives_traits::{
|
||||
transaction::error::{TransactionConversionError, TryFromRecoveredTransactionError},
|
||||
InMemorySize, Recovered, SignedTransaction,
|
||||
transaction::error::TryFromRecoveredTransactionError, InMemorySize, Recovered,
|
||||
SignedTransaction,
|
||||
};
|
||||
|
||||
use alloy_consensus::error::ValueError;
|
||||
use alloy_eips::eip4844::env_settings::KzgSettings;
|
||||
use rand::distr::weighted::WeightedIndex;
|
||||
use std::{ops::Range, sync::Arc, time::Instant, vec::IntoIter};
|
||||
@@ -667,7 +668,7 @@ impl MockTransaction {
|
||||
}
|
||||
|
||||
impl PoolTransaction for MockTransaction {
|
||||
type TryFromConsensusError = TransactionConversionError;
|
||||
type TryFromConsensusError = ValueError<EthereumTxEnvelope<TxEip4844>>;
|
||||
|
||||
type Consensus = TransactionSigned;
|
||||
|
||||
@@ -918,8 +919,7 @@ impl TryFrom<Recovered<TransactionSigned>> for MockTransaction {
|
||||
let hash = *transaction.tx_hash();
|
||||
let size = transaction.size();
|
||||
|
||||
#[expect(unreachable_patterns)]
|
||||
match transaction.into_transaction() {
|
||||
match transaction.into_typed_transaction() {
|
||||
Transaction::Legacy(TxLegacy {
|
||||
chain_id,
|
||||
nonce,
|
||||
@@ -1046,7 +1046,6 @@ impl TryFrom<Recovered<TransactionSigned>> for MockTransaction {
|
||||
size,
|
||||
cost: U256::from(gas_limit) * U256::from(max_fee_per_gas) + value,
|
||||
}),
|
||||
tx => Err(TryFromRecoveredTransactionError::UnsupportedTransactionType(tx.ty())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1167,10 +1166,12 @@ impl From<Recovered<PooledTransaction>> for MockTransaction {
|
||||
|
||||
impl From<MockTransaction> for Recovered<TransactionSigned> {
|
||||
fn from(tx: MockTransaction) -> Self {
|
||||
let signed_tx =
|
||||
TransactionSigned::new(tx.clone().into(), Signature::test_signature(), *tx.hash());
|
||||
|
||||
Self::new_unchecked(signed_tx, tx.sender())
|
||||
let hash = *tx.hash();
|
||||
let sender = tx.sender();
|
||||
let tx = Transaction::from(tx);
|
||||
let tx: TransactionSigned =
|
||||
Signed::new_unchecked(tx, Signature::test_signature(), hash).into();
|
||||
Self::new_unchecked(tx, sender)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@ use crate::{
|
||||
validate::ValidPoolTransaction,
|
||||
AllTransactionsEvents,
|
||||
};
|
||||
use alloy_consensus::{transaction::PooledTransaction, BlockHeader, Signed, Typed2718};
|
||||
use alloy_consensus::{
|
||||
error::ValueError, transaction::PooledTransaction, BlockHeader, Signed, Typed2718,
|
||||
};
|
||||
use alloy_eips::{
|
||||
eip2718::Encodable2718,
|
||||
eip2930::AccessList,
|
||||
@@ -21,12 +23,9 @@ use alloy_eips::{
|
||||
use alloy_primitives::{Address, Bytes, TxHash, TxKind, B256, U256};
|
||||
use futures_util::{ready, Stream};
|
||||
use reth_eth_wire_types::HandleMempoolData;
|
||||
use reth_ethereum_primitives::{Transaction, TransactionSigned};
|
||||
use reth_ethereum_primitives::TransactionSigned;
|
||||
use reth_execution_types::ChangedAccount;
|
||||
use reth_primitives_traits::{
|
||||
transaction::error::TransactionConversionError, Block, InMemorySize, Recovered, SealedBlock,
|
||||
SignedTransaction,
|
||||
};
|
||||
use reth_primitives_traits::{Block, InMemorySize, Recovered, SealedBlock, SignedTransaction};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
@@ -1121,7 +1120,7 @@ impl<T: SignedTransaction> EthPooledTransaction<T> {
|
||||
}
|
||||
|
||||
impl PoolTransaction for EthPooledTransaction {
|
||||
type TryFromConsensusError = TransactionConversionError;
|
||||
type TryFromConsensusError = ValueError<TransactionSigned>;
|
||||
|
||||
type Consensus = TransactionSigned;
|
||||
|
||||
@@ -1307,8 +1306,8 @@ impl EthPoolTransaction for EthPooledTransaction {
|
||||
sidecar: &BlobTransactionSidecar,
|
||||
settings: &KzgSettings,
|
||||
) -> Result<(), BlobTransactionValidationError> {
|
||||
match self.transaction.transaction() {
|
||||
Transaction::Eip4844(tx) => tx.validate_blob(sidecar, settings),
|
||||
match self.transaction.inner().as_eip4844() {
|
||||
Some(tx) => tx.tx().validate_blob(sidecar, settings),
|
||||
_ => Err(BlobTransactionValidationError::NotBlobTransaction(self.ty())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -990,7 +990,6 @@ mod tests {
|
||||
use alloy_eips::eip2718::Decodable2718;
|
||||
use alloy_primitives::{hex, U256};
|
||||
use reth_ethereum_primitives::PooledTransaction;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::test_utils::{ExtendedAccount, MockEthProvider};
|
||||
|
||||
fn get_transaction() -> EthPooledTransaction {
|
||||
|
||||
@@ -10,7 +10,7 @@ use futures_util::{stream::FuturesUnordered, Future, Stream, StreamExt};
|
||||
use reqwest::{Error, StatusCode};
|
||||
use reth_ethereum::{
|
||||
pool::{BlobStoreError, TransactionPoolExt},
|
||||
primitives::{RecoveredBlock, SignedTransaction},
|
||||
primitives::RecoveredBlock,
|
||||
provider::CanonStateNotification,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -15,7 +15,7 @@ use reth::{
|
||||
use reth_ethereum::{
|
||||
chainspec::ChainSpec,
|
||||
node::{
|
||||
core::{args::RpcServerArgs, node_config::NodeConfig, primitives::SignedTransaction},
|
||||
core::{args::RpcServerArgs, node_config::NodeConfig},
|
||||
EthereumNode,
|
||||
},
|
||||
provider::CanonStateSubscriptions,
|
||||
|
||||
@@ -4,9 +4,7 @@ use alloy_primitives::{Address, B256};
|
||||
use reth_ethereum::{
|
||||
chainspec::ChainSpecBuilder,
|
||||
node::EthereumNode,
|
||||
primitives::{
|
||||
transaction::signed::SignedTransaction, AlloyBlockHeader, SealedBlock, SealedHeader,
|
||||
},
|
||||
primitives::{AlloyBlockHeader, SealedBlock, SealedHeader},
|
||||
provider::{
|
||||
providers::ReadOnlyConfig, AccountReader, BlockReader, BlockSource, HeaderProvider,
|
||||
ReceiptProvider, StateProvider, TransactionsProvider,
|
||||
|
||||
@@ -172,7 +172,7 @@ pub fn sign_tx_with_key_pair(key_pair: Keypair, tx: Transaction) -> TransactionS
|
||||
let signature =
|
||||
sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), tx.signature_hash()).unwrap();
|
||||
|
||||
TransactionSigned::new_unhashed(tx, signature)
|
||||
tx.into_signed(signature).into()
|
||||
}
|
||||
|
||||
/// Generates a new random [Keypair].
|
||||
@@ -211,7 +211,7 @@ pub fn random_block<R: Rng>(
|
||||
let tx_count = block_params.tx_count.unwrap_or_else(|| rng.random::<u8>());
|
||||
let transactions: Vec<TransactionSigned> =
|
||||
(0..tx_count).map(|_| random_signed_tx(rng)).collect();
|
||||
let total_gas = transactions.iter().fold(0, |sum, tx| sum + tx.transaction().gas_limit());
|
||||
let total_gas = transactions.iter().fold(0, |sum, tx| sum + tx.gas_limit());
|
||||
|
||||
// Generate ommers
|
||||
let ommers_count = block_params.ommers_count.unwrap_or_else(|| rng.random_range(0..2));
|
||||
@@ -488,10 +488,7 @@ mod tests {
|
||||
use alloy_consensus::TxEip1559;
|
||||
use alloy_eips::eip2930::AccessList;
|
||||
use alloy_primitives::{hex, Signature};
|
||||
use reth_primitives_traits::{
|
||||
crypto::secp256k1::{public_key_to_address, sign_message},
|
||||
SignedTransaction,
|
||||
};
|
||||
use reth_primitives_traits::crypto::secp256k1::{public_key_to_address, sign_message};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
@@ -518,7 +515,7 @@ mod tests {
|
||||
sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), signature_hash)
|
||||
.unwrap();
|
||||
|
||||
let signed = TransactionSigned::new_unhashed(tx.clone(), signature);
|
||||
let signed: TransactionSigned = tx.clone().into_signed(signature).into();
|
||||
let recovered = signed.recover_signer().unwrap();
|
||||
|
||||
let expected = public_key_to_address(key_pair.public_key());
|
||||
|
||||
Reference in New Issue
Block a user