impl Encodable2718, Decodable2718 for TransactionSigned (#11218)

This commit is contained in:
Arsenii Kulikov
2024-09-30 19:36:38 +04:00
committed by GitHub
parent 24b6341205
commit 42afcbd75a
26 changed files with 211 additions and 317 deletions

58
Cargo.lock generated
View File

@ -1601,9 +1601,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.1.22"
version = "1.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17"
dependencies = [
"jobserver",
"libc",
@ -1858,9 +1858,9 @@ dependencies = [
[[package]]
name = "const-hex"
version = "1.12.0"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6"
checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586"
dependencies = [
"cfg-if",
"cpufeatures",
@ -4460,7 +4460,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.6.0",
"libc",
"redox_syscall 0.5.6",
"redox_syscall 0.5.7",
]
[[package]]
@ -5088,9 +5088,12 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.19.0"
version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1"
dependencies = [
"portable-atomic",
]
[[package]]
name = "oorandom"
@ -5329,7 +5332,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.6",
"redox_syscall 0.5.7",
"smallvec",
"windows-targets 0.52.6",
]
@ -5745,7 +5748,7 @@ dependencies = [
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand_xorshift",
"regex-syntax 0.8.4",
"regex-syntax 0.8.5",
"rusty-fork",
"tempfile",
"unarray",
@ -6022,9 +6025,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.6"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags 2.6.0",
]
@ -6042,14 +6045,14 @@ dependencies = [
[[package]]
name = "regex"
version = "1.10.6"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.4.7",
"regex-syntax 0.8.4",
"regex-automata 0.4.8",
"regex-syntax 0.8.5",
]
[[package]]
@ -6063,13 +6066,13 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.7"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.8.4",
"regex-syntax 0.8.5",
]
[[package]]
@ -6080,9 +6083,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "regress"
@ -6154,6 +6157,7 @@ name = "reth"
version = "1.0.7"
dependencies = [
"alloy-consensus",
"alloy-eips",
"alloy-primitives",
"alloy-rlp",
"alloy-rpc-types",
@ -7997,6 +8001,7 @@ name = "reth-optimism-evm"
version = "1.0.7"
dependencies = [
"alloy-consensus",
"alloy-eips",
"alloy-genesis",
"alloy-primitives",
"reth-chainspec",
@ -8031,6 +8036,7 @@ dependencies = [
name = "reth-optimism-node"
version = "1.0.7"
dependencies = [
"alloy-eips",
"alloy-genesis",
"alloy-primitives",
"alloy-rpc-types-engine",
@ -8083,6 +8089,7 @@ dependencies = [
name = "reth-optimism-payload-builder"
version = "1.0.7"
dependencies = [
"alloy-eips",
"alloy-primitives",
"alloy-rlp",
"alloy-rpc-types-engine",
@ -8124,6 +8131,7 @@ dependencies = [
name = "reth-optimism-rpc"
version = "1.0.7"
dependencies = [
"alloy-eips",
"alloy-primitives",
"alloy-rpc-types",
"alloy-rpc-types-eth",
@ -8410,6 +8418,7 @@ version = "1.0.7"
dependencies = [
"alloy-consensus",
"alloy-dyn-abi",
"alloy-eips",
"alloy-genesis",
"alloy-network",
"alloy-primitives",
@ -8730,6 +8739,7 @@ dependencies = [
name = "reth-rpc-types-compat"
version = "1.0.7"
dependencies = [
"alloy-eips",
"alloy-primitives",
"alloy-rlp",
"alloy-rpc-types",
@ -9516,9 +9526,9 @@ dependencies = [
[[package]]
name = "scc"
version = "2.1.17"
version = "2.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c947adb109a8afce5fc9c7bf951f87f146e9147b3a6a58413105628fb1d1e66"
checksum = "215b1103f73e23e9cb6883072c1fb26ae55c09d42054654955c739e5418a7c96"
dependencies = [
"sdd",
]
@ -10880,9 +10890,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "ucd-trie"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "uint"

View File

@ -66,6 +66,7 @@ reth-engine-util.workspace = true
reth-prune.workspace = true
# crypto
alloy-eips.workspace = true
alloy-rlp.workspace = true
alloy-rpc-types = { workspace = true, features = ["engine"] }
alloy-consensus.workspace = true

View File

@ -1,5 +1,6 @@
//! Command for debugging block building.
use alloy_consensus::TxEip4844;
use alloy_eips::eip2718::Encodable2718;
use alloy_primitives::{Address, Bytes, B256, U256};
use alloy_rlp::Decodable;
use alloy_rpc_types::engine::{BlobsBundleV1, PayloadAttributes};
@ -200,7 +201,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
encoded_length
}
_ => transaction.length_without_header(),
_ => transaction.encode_2718_len(),
};
debug!(target: "reth::cli", ?transaction, "Adding transaction to the pool");

View File

@ -38,6 +38,8 @@ thiserror.workspace = true
tracing.workspace = true
[dev-dependencies]
alloy-eips.workspace = true
reth-revm = { workspace = true, features = ["test-utils"] }
reth-optimism-chainspec.workspace = true
alloy-genesis.workspace = true

View File

@ -299,6 +299,7 @@ where
#[cfg(test)]
mod tests {
use alloy_eips::eip2718::Decodable2718;
use reth_optimism_chainspec::OP_MAINNET;
use reth_optimism_forks::OptimismHardforks;
use reth_primitives::{BlockBody, TransactionSigned};
@ -311,7 +312,7 @@ mod tests {
use reth_primitives::{Header, TransactionSigned};
let bytes = Bytes::from_static(&hex!("7ef9015aa044bae9d41b8380d781187b426c6fe43df5fb2fb57bd4466ef6a701e1f01e015694deaddeaddeaddeaddeaddeaddeaddeaddead000194420000000000000000000000000000000000001580808408f0d18001b90104015d8eb900000000000000000000000000000000000000000000000000000000008057650000000000000000000000000000000000000000000000000000000063d96d10000000000000000000000000000000000000000000000000000000000009f35273d89754a1e0387b89520d989d3be9c37c1f32495a88faf1ea05c61121ab0d1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000002d679b567db6187c0c8323fa982cfb88b74dbcc7000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240"));
let l1_info_tx = TransactionSigned::decode_enveloped(&mut bytes.as_ref()).unwrap();
let l1_info_tx = TransactionSigned::decode_2718(&mut bytes.as_ref()).unwrap();
let mock_block = Block {
header: Header::default(),
body: BlockBody { transactions: vec![l1_info_tx], ..Default::default() },
@ -339,7 +340,7 @@ mod tests {
// https://optimistic.etherscan.io/getRawTx?tx=0x88501da5d5ca990347c2193be90a07037af1e3820bb40774c8154871c7669150
const TX: [u8; 251] = hex!("7ef8f8a0a539eb753df3b13b7e386e147d45822b67cb908c9ddc5618e3dbaa22ed00850b94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e2000000558000c5fc50000000000000000000000006605a89f00000000012a10d90000000000000000000000000000000000000000000000000000000af39ac3270000000000000000000000000000000000000000000000000000000d5ea528d24e582fa68786f080069bdbfe06a43f8e67bfd31b8e4d8a8837ba41da9a82a54a0000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985");
let tx = TransactionSigned::decode_enveloped(&mut TX.as_slice()).unwrap();
let tx = TransactionSigned::decode_2718(&mut TX.as_slice()).unwrap();
let block = Block {
body: BlockBody { transactions: vec![tx], ..Default::default() },
..Default::default()

View File

@ -43,6 +43,7 @@ reth-optimism-consensus.workspace = true
reth-optimism-forks.workspace = true
# ethereum
alloy-eips.workspace = true
alloy-primitives.workspace = true
op-alloy-rpc-types-engine.workspace = true
alloy-rpc-types-engine.workspace = true

View File

@ -1,4 +1,5 @@
//! OP transaction pool types
use alloy_eips::eip2718::Encodable2718;
use parking_lot::RwLock;
use reth_chainspec::ChainSpec;
use reth_optimism_evm::RethL1BlockInfo;
@ -139,7 +140,7 @@ where
let l1_block_info = self.block_info.l1_block_info.read().clone();
let mut encoded = Vec::with_capacity(valid_tx.transaction().encoded_length());
valid_tx.transaction().clone().into_consensus().encode_enveloped(&mut encoded);
valid_tx.transaction().clone().into_consensus().encode_2718(&mut encoded);
let cost_addition = match l1_block_info.l1_tx_data_fee(
&self.chain_spec(),
@ -229,6 +230,7 @@ pub struct OpL1BlockInfo {
#[cfg(test)]
mod tests {
use crate::txpool::OpTransactionValidator;
use alloy_eips::eip2718::Encodable2718;
use alloy_primitives::{TxKind, U256};
use reth::primitives::Signature;
use reth_chainspec::MAINNET;
@ -266,7 +268,7 @@ mod tests {
let signed_tx = TransactionSigned::from_transaction_and_signature(deposit_tx, signature);
let signed_recovered =
TransactionSignedEcRecovered::from_signed_transaction(signed_tx, signer);
let len = signed_recovered.length_without_header();
let len = signed_recovered.encode_2718_len();
let pooled_tx = EthPooledTransaction::new(signed_recovered, len);
let outcome = validator.validate_one(origin, pooled_tx);

View File

@ -35,6 +35,7 @@ reth-optimism-forks.workspace = true
# ethereum
revm.workspace = true
alloy-eips.workspace = true
alloy-primitives.workspace = true
alloy-rlp.workspace = true
op-alloy-rpc-types-engine.workspace = true

View File

@ -2,6 +2,7 @@
//! Optimism builder support
use alloy_eips::eip2718::Decodable2718;
use alloy_primitives::{Address, B256, U256};
use alloy_rlp::Encodable;
use alloy_rpc_types_engine::{ExecutionPayloadEnvelopeV2, ExecutionPayloadV1, PayloadId};
@ -53,8 +54,15 @@ impl PayloadBuilderAttributes for OptimismPayloadBuilderAttributes {
.unwrap_or_default()
.into_iter()
.map(|data| {
TransactionSigned::decode_enveloped(&mut data.as_ref())
.map(|tx| WithEncoded::new(data, tx))
let mut buf = data.as_ref();
let tx =
TransactionSigned::decode_2718(&mut buf).map_err(alloy_rlp::Error::from)?;
if !buf.is_empty() {
return Err(alloy_rlp::Error::UnexpectedLength);
}
Ok(WithEncoded::new(data, tx))
})
.collect::<Result<_, _>>()?;

View File

@ -34,6 +34,7 @@ reth-optimism-evm.workspace = true
reth-optimism-forks.workspace = true
# ethereum
alloy-eips.workspace = true
alloy-primitives.workspace = true
alloy-rpc-types-eth.workspace = true
alloy-rpc-types.workspace = true

View File

@ -1,5 +1,6 @@
//! Loads and formats OP receipt RPC response.
use alloy_eips::eip2718::Encodable2718;
use alloy_rpc_types::{AnyReceiptEnvelope, Log, TransactionReceipt};
use op_alloy_consensus::{OpDepositReceipt, OpDepositReceiptWithBloom, OpReceiptEnvelope};
use op_alloy_rpc_types::{
@ -119,7 +120,7 @@ impl OpReceiptFieldsBuilder {
tx: &TransactionSigned,
l1_block_info: revm::L1BlockInfo,
) -> Result<Self, OpEthApiError> {
let raw_tx = tx.envelope_encoded();
let raw_tx = tx.encoded_2718();
let timestamp = self.l1_block_timestamp;
self.l1_fee = Some(
@ -300,6 +301,7 @@ impl OpReceiptBuilder {
#[cfg(test)]
mod test {
use alloy_primitives::hex;
use op_alloy_network::eip2718::Decodable2718;
use reth_optimism_chainspec::OP_MAINNET;
use reth_primitives::{Block, BlockBody};
@ -341,14 +343,13 @@ mod test {
#[test]
fn op_receipt_fields_from_block_and_tx() {
// rig
let tx_0 = TransactionSigned::decode_enveloped(
let tx_0 = TransactionSigned::decode_2718(
&mut TX_SET_L1_BLOCK_OP_MAINNET_BLOCK_124665056.as_slice(),
)
.unwrap();
let tx_1 =
TransactionSigned::decode_enveloped(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice())
.unwrap();
let tx_1 = TransactionSigned::decode_2718(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice())
.unwrap();
let block = Block {
body: BlockBody { transactions: [tx_0, tx_1.clone()].to_vec(), ..Default::default() },

View File

@ -5,6 +5,7 @@ use alloc::vec::Vec;
pub use alloy_eips::eip1898::{
BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag, ForkBlock, RpcBlockHash,
};
use alloy_eips::eip2718::Encodable2718;
use alloy_primitives::{Address, Bytes, Sealable, B256};
use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable};
use derive_more::{Deref, DerefMut};
@ -463,9 +464,10 @@ impl SealedBlock {
Ok(())
}
/// Returns a vector of transactions RLP encoded with [`TransactionSigned::encode_enveloped`].
/// Returns a vector of transactions RLP encoded with
/// [`alloy_eips::eip2718::Encodable2718::encoded_2718`].
pub fn raw_transactions(&self) -> Vec<Bytes> {
self.body.transactions().map(|tx| tx.envelope_encoded()).collect()
self.body.transactions().map(|tx| tx.encoded_2718().into()).collect()
}
}

View File

@ -5,7 +5,7 @@ use crate::{
Request, TransactionSigned, Withdrawal,
};
use alloc::vec::Vec;
use alloy_eips::eip7685::Encodable7685;
use alloy_eips::{eip2718::Encodable2718, eip7685::Encodable7685};
use alloy_primitives::{keccak256, B256};
use reth_trie_common::root::{ordered_trie_root, ordered_trie_root_with_encoder};
@ -16,7 +16,7 @@ pub fn calculate_transaction_root<T>(transactions: &[T]) -> B256
where
T: AsRef<TransactionSigned>,
{
ordered_trie_root_with_encoder(transactions, |tx: &T, buf| tx.as_ref().encode_inner(buf, false))
ordered_trie_root_with_encoder(transactions, |tx: &T, buf| tx.as_ref().encode_2718(buf))
}
/// Calculates the root hash of the withdrawals.

View File

@ -11,11 +11,7 @@ pub trait FillTxEnv {
impl FillTxEnv for TransactionSigned {
fn fill_tx_env(&self, tx_env: &mut TxEnv, sender: Address) {
#[cfg(feature = "optimism")]
let envelope = {
let mut envelope = alloc::vec::Vec::with_capacity(self.length_without_header());
self.encode_enveloped(&mut envelope);
envelope
};
let envelope = alloy_eips::eip2718::Encodable2718::encoded_2718(self);
tx_env.caller = sender;
match self.as_ref() {

View File

@ -5,12 +5,12 @@ use alloy_eips::eip7702::SignedAuthorization;
use alloy_primitives::{keccak256, Address, TxKind, B256, U256};
use alloy_consensus::{SignableTransaction, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy};
use alloy_eips::eip2930::AccessList;
use alloy_primitives::{Bytes, Parity, TxHash};
use alloy_rlp::{
Decodable, Encodable, Error as RlpError, Header, EMPTY_LIST_CODE, EMPTY_STRING_CODE,
use alloy_eips::{
eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718},
eip2930::AccessList,
};
use bytes::Buf;
use alloy_primitives::{Bytes, TxHash};
use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header};
use core::mem;
use derive_more::{AsRef, Deref};
use once_cell::sync::Lazy;
@ -730,6 +730,8 @@ impl reth_codecs::Compact for Transaction {
// A panic will be triggered if an identifier larger than 3 is passed from the database. For
// optimism a identifier with value [`DEPOSIT_TX_TYPE_ID`] is allowed.
fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
use bytes::Buf;
match identifier {
COMPACT_IDENTIFIER_LEGACY => {
let (tx, buf) = TxLegacy::from_compact(buf, buf.len());
@ -975,6 +977,8 @@ impl reth_codecs::Compact for TransactionSignedNoHash {
}
fn from_compact(mut buf: &[u8], _len: usize) -> (Self, &[u8]) {
use bytes::Buf;
// The first byte uses 4 bits as flags: IsCompressed[1], TxType[2], Signature[1]
let bitflags = buf.get_u8() as usize;
@ -1196,62 +1200,10 @@ impl TransactionSigned {
}
}
/// Returns the enveloped encoded transactions.
///
/// See also [`TransactionSigned::encode_enveloped`]
pub fn envelope_encoded(&self) -> Bytes {
let mut buf = Vec::new();
self.encode_enveloped(&mut buf);
buf.into()
}
/// Encodes the transaction into the "raw" format (e.g. `eth_sendRawTransaction`).
/// This format is also referred to as "binary" encoding.
///
/// For legacy transactions, it encodes the RLP of the transaction into the buffer:
/// `rlp(tx-data)`
/// For EIP-2718 typed it encodes the type of the transaction followed by the rlp of the
/// transaction: `tx-type || rlp(tx-data)`
pub fn encode_enveloped(&self, out: &mut dyn bytes::BufMut) {
self.encode_inner(out, false)
}
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
/// hash that for eip2718 does not require rlp header
pub(crate) fn encode_inner(&self, out: &mut dyn bytes::BufMut, with_header: bool) {
self.transaction.encode_with_signature(&self.signature, out, with_header);
}
/// Output the length of the `encode_inner(out`, true). Note to assume that `with_header` is
/// only `true`.
pub(crate) fn payload_len_inner(&self) -> usize {
match &self.transaction {
Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature(
&with_eip155_parity(&self.signature, legacy_tx.chain_id),
),
Transaction::Eip2930(access_list_tx) => {
access_list_tx.encoded_len_with_signature(&self.signature, true)
}
Transaction::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.encoded_len_with_signature(&self.signature, true)
}
Transaction::Eip4844(blob_tx) => {
blob_tx.encoded_len_with_signature(&self.signature, true)
}
Transaction::Eip7702(set_code_tx) => {
set_code_tx.encoded_len_with_signature(&self.signature, true)
}
#[cfg(feature = "optimism")]
Transaction::Deposit(deposit_tx) => deposit_tx.encoded_len(true),
}
}
/// Calculate transaction hash, eip2728 transaction does not contain rlp header and start with
/// tx type.
pub fn recalculate_hash(&self) -> B256 {
let mut buf = Vec::new();
self.encode_inner(&mut buf, false);
keccak256(&buf)
keccak256(self.encoded_2718())
}
/// Create a new signed transaction from a transaction and its signature.
@ -1329,134 +1281,6 @@ impl TransactionSigned {
let signed = Self { transaction: Transaction::Legacy(transaction), hash, signature };
Ok(signed)
}
/// Decodes an enveloped EIP-2718 typed transaction.
///
/// This should _only_ be used internally in general transaction decoding methods,
/// which have already ensured that the input is a typed transaction with the following format:
/// `tx-type || rlp(tx-data)`
///
/// Note that this format does not start with any RLP header, and instead starts with a single
/// byte indicating the transaction type.
///
/// CAUTION: this expects that `data` is `tx-type || rlp(tx-data)`
pub fn decode_enveloped_typed_transaction(data: &mut &[u8]) -> alloy_rlp::Result<Self> {
// keep this around so we can use it to calculate the hash
let original_encoding_without_header = *data;
let tx_type = *data.first().ok_or(RlpError::InputTooShort)?;
data.advance(1);
// decode the list header for the rest of the transaction
let header = Header::decode(data)?;
if !header.list {
return Err(RlpError::Custom("typed tx fields must be encoded as a list"))
}
let remaining_len = data.len();
// length of tx encoding = tx type byte (size = 1) + length of header + payload length
let tx_length = 1 + header.length() + header.payload_length;
// decode common fields
let Ok(tx_type) = TxType::try_from(tx_type) else {
return Err(RlpError::Custom("unsupported typed transaction type"))
};
let transaction = match tx_type {
TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_fields(data)?),
TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_fields(data)?),
TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_fields(data)?),
TxType::Eip7702 => Transaction::Eip7702(TxEip7702::decode_fields(data)?),
#[cfg(feature = "optimism")]
TxType::Deposit => Transaction::Deposit(TxDeposit::decode_fields(data)?),
TxType::Legacy => return Err(RlpError::Custom("unexpected legacy tx type")),
};
#[cfg(not(feature = "optimism"))]
let signature = Signature::decode_rlp_vrs(data)?;
#[cfg(feature = "optimism")]
let signature = if tx_type == TxType::Deposit {
optimism_deposit_tx_signature()
} else {
Signature::decode_rlp_vrs(data)?
};
if !matches!(signature.v(), Parity::Parity(_)) {
return Err(alloy_rlp::Error::Custom("invalid parity for typed transaction"));
}
let bytes_consumed = remaining_len - data.len();
if bytes_consumed != header.payload_length {
return Err(RlpError::UnexpectedLength)
}
let hash = keccak256(&original_encoding_without_header[..tx_length]);
let signed = Self { transaction, hash, signature };
Ok(signed)
}
/// Decodes the "raw" format of transaction (similar to `eth_sendRawTransaction`).
///
/// This should be used for any RPC method that accepts a raw transaction.
/// Currently, this includes:
/// * `eth_sendRawTransaction`.
/// * All versions of `engine_newPayload`, in the `transactions` field.
///
/// A raw transaction is either a legacy transaction or EIP-2718 typed transaction.
///
/// For legacy transactions, the format is encoded as: `rlp(tx-data)`. This format will start
/// with a RLP list header.
///
/// For EIP-2718 typed transactions, the format is encoded as the type of the transaction
/// followed by the rlp of the transaction: `type || rlp(tx-data)`.
///
/// Both for legacy and EIP-2718 transactions, an error will be returned if there is an excess
/// of bytes in input data.
pub fn decode_enveloped(input_data: &mut &[u8]) -> alloy_rlp::Result<Self> {
if input_data.is_empty() {
return Err(RlpError::InputTooShort)
}
// Check if the tx is a list
let output_data = if input_data[0] >= EMPTY_LIST_CODE {
// decode as legacy transaction
Self::decode_rlp_legacy_transaction(input_data)?
} else {
Self::decode_enveloped_typed_transaction(input_data)?
};
if !input_data.is_empty() {
return Err(RlpError::UnexpectedLength)
}
Ok(output_data)
}
/// Returns the length without an RLP header - this is used for eth/68 sizes.
pub fn length_without_header(&self) -> usize {
// method computes the payload len without a RLP header
match &self.transaction {
Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature(
&with_eip155_parity(&self.signature, legacy_tx.chain_id),
),
Transaction::Eip2930(access_list_tx) => {
access_list_tx.encoded_len_with_signature(&self.signature, false)
}
Transaction::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.encoded_len_with_signature(&self.signature, false)
}
Transaction::Eip4844(blob_tx) => {
blob_tx.encoded_len_with_signature(&self.signature, false)
}
Transaction::Eip7702(set_code_tx) => {
set_code_tx.encoded_len_with_signature(&self.signature, false)
}
#[cfg(feature = "optimism")]
Transaction::Deposit(deposit_tx) => deposit_tx.encoded_len(false),
}
}
}
impl From<TransactionSignedEcRecovered> for TransactionSigned {
@ -1475,11 +1299,16 @@ impl Encodable for TransactionSigned {
/// transaction:
/// `rlp(tx-type || rlp(tx-data))`
fn encode(&self, out: &mut dyn bytes::BufMut) {
self.encode_inner(out, true);
self.network_encode(out);
}
fn length(&self) -> usize {
self.payload_len_inner()
let mut payload_length = self.encode_2718_len();
if !self.is_legacy() {
payload_length += Header { list: false, payload_length }.length();
}
payload_length
}
}
@ -1510,38 +1339,76 @@ impl Decodable for TransactionSigned {
/// This is because [`Header::decode`] does not advance the buffer, and returns a length-1
/// string header if the first byte is less than `0xf7`.
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
if buf.is_empty() {
return Err(RlpError::InputTooShort)
Self::network_decode(buf).map_err(Into::into)
}
}
impl Encodable2718 for TransactionSigned {
fn type_flag(&self) -> Option<u8> {
match self.transaction.tx_type() {
TxType::Legacy => None,
tx_type => Some(tx_type as u8),
}
}
// decode header
let mut original_encoding = *buf;
let header = Header::decode(buf)?;
let remaining_len = buf.len();
// if the transaction is encoded as a string then it is a typed transaction
if header.list {
let tx = Self::decode_rlp_legacy_transaction(&mut original_encoding)?;
// advance the buffer based on how far `decode_rlp_legacy_transaction` advanced the
// buffer
*buf = original_encoding;
Ok(tx)
} else {
let tx = Self::decode_enveloped_typed_transaction(buf)?;
let bytes_consumed = remaining_len - buf.len();
// because Header::decode works for single bytes (including the tx type), returning a
// string Header with payload_length of 1, we need to make sure this check is only
// performed for transactions with a string header
if bytes_consumed != header.payload_length && original_encoding[0] > EMPTY_STRING_CODE {
return Err(RlpError::UnexpectedLength)
fn encode_2718_len(&self) -> usize {
match &self.transaction {
Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature(
&with_eip155_parity(&self.signature, legacy_tx.chain_id),
),
Transaction::Eip2930(access_list_tx) => {
access_list_tx.encoded_len_with_signature(&self.signature, false)
}
Ok(tx)
Transaction::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.encoded_len_with_signature(&self.signature, false)
}
Transaction::Eip4844(blob_tx) => {
blob_tx.encoded_len_with_signature(&self.signature, false)
}
Transaction::Eip7702(set_code_tx) => {
set_code_tx.encoded_len_with_signature(&self.signature, false)
}
#[cfg(feature = "optimism")]
Transaction::Deposit(deposit_tx) => deposit_tx.encoded_len(false),
}
}
fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) {
self.transaction.encode_with_signature(&self.signature, out, false)
}
}
impl Decodable2718 for TransactionSigned {
fn typed_decode(ty: u8, buf: &mut &[u8]) -> Eip2718Result<Self> {
match ty.try_into().map_err(|_| Eip2718Error::UnexpectedType(ty))? {
TxType::Legacy => Err(Eip2718Error::UnexpectedType(0)),
TxType::Eip2930 => {
let (tx, signature, hash) = TxEip2930::decode_signed_fields(buf)?.into_parts();
Ok(Self { transaction: Transaction::Eip2930(tx), signature, hash })
}
TxType::Eip1559 => {
let (tx, signature, hash) = TxEip1559::decode_signed_fields(buf)?.into_parts();
Ok(Self { transaction: Transaction::Eip1559(tx), signature, hash })
}
TxType::Eip7702 => {
let (tx, signature, hash) = TxEip7702::decode_signed_fields(buf)?.into_parts();
Ok(Self { transaction: Transaction::Eip7702(tx), signature, hash })
}
TxType::Eip4844 => {
let (tx, signature, hash) = TxEip4844::decode_signed_fields(buf)?.into_parts();
Ok(Self { transaction: Transaction::Eip4844(tx), signature, hash })
}
#[cfg(feature = "optimism")]
TxType::Deposit => Ok(Self::from_transaction_and_signature(
Transaction::Deposit(TxDeposit::decode(buf)?),
optimism_deposit_tx_signature(),
)),
}
}
fn fallback_decode(buf: &mut &[u8]) -> Eip2718Result<Self> {
Ok(Self::decode_rlp_legacy_transaction(buf)?)
}
}
#[cfg(any(test, feature = "arbitrary"))]
@ -1702,6 +1569,7 @@ mod tests {
transaction::{signature::Signature, TxEip1559, TxKind, TxLegacy},
Transaction, TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash,
};
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
use alloy_primitives::{address, b256, bytes, hex, Address, Bytes, Parity, B256, U256};
use alloy_rlp::{Decodable, Encodable, Error as RlpError};
use reth_chainspec::MIN_TRANSACTION_GAS;
@ -1743,7 +1611,7 @@ mod tests {
// random mainnet tx <https://etherscan.io/tx/0x86718885c4b4218c6af87d3d0b0d83e3cc465df2a05c048aa4db9f1a6f9de91f>
let tx_bytes = hex!("02f872018307910d808507204d2cb1827d0094388c818ca8b9251b393131c08a736a67ccb19297880320d04823e2701c80c001a0cf024f4815304df2867a1a74e9d2707b6abda0337d2d54a4438d453f4160f190a07ac0e6b3bc9395b5b9c8b9e6d77204a236577a5b18467b9175c01de4faa208d9");
let decoded = TransactionSigned::decode_enveloped(&mut &tx_bytes[..]).unwrap();
let decoded = TransactionSigned::decode_2718(&mut &tx_bytes[..]).unwrap();
assert_eq!(
decoded.recover_signer(),
Some(Address::from_str("0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5").unwrap())
@ -1759,7 +1627,7 @@ mod tests {
// https://sepolia.etherscan.io/getRawTx?tx=0x9a22ccb0029bc8b0ddd073be1a1d923b7ae2b2ea52100bae0db4424f9107e9c0
let raw_tx = alloy_primitives::hex::decode("0x03f9011d83aa36a7820fa28477359400852e90edd0008252089411e9ca82a3a762b4b5bd264d4173a242e7a770648080c08504a817c800f8a5a0012ec3d6f66766bedb002a190126b3549fce0047de0d4c25cffce0dc1c57921aa00152d8e24762ff22b1cfd9f8c0683786a7ca63ba49973818b3d1e9512cd2cec4a0013b98c6c83e066d5b14af2b85199e3d4fc7d1e778dd53130d180f5077e2d1c7a001148b495d6e859114e670ca54fb6e2657f0cbae5b08063605093a4b3dc9f8f1a0011ac212f13c5dff2b2c6b600a79635103d6f580a4221079951181b25c7e654901a0c8de4cced43169f9aa3d36506363b2d2c44f6c49fc1fd91ea114c86f3757077ea01e11fdd0d1934eda0492606ee0bb80a7bf8f35cc5f86ec60fe5031ba48bfd544").unwrap();
let decoded = TransactionSigned::decode_enveloped(&mut raw_tx.as_slice()).unwrap();
let decoded = TransactionSigned::decode_2718(&mut raw_tx.as_slice()).unwrap();
assert_eq!(decoded.tx_type(), TxType::Eip4844);
let from = decoded.recover_signer();
@ -1933,7 +1801,7 @@ mod tests {
let input = hex!("02f871018302a90f808504890aef60826b6c94ddf4c5025d1a5742cf12f74eec246d4432c295e487e09c3bbcc12b2b80c080a0f21a4eacd0bf8fea9c5105c543be5a1d8c796516875710fafafdf16d16d8ee23a001280915021bb446d1973501a67f93d2b38894a514b976e7b46dc2fe54598d76");
let decoded = TransactionSigned::decode(&mut &input[..]).unwrap();
let encoded = decoded.envelope_encoded();
let encoded = decoded.encoded_2718();
assert_eq!(encoded[..], input);
}
@ -1941,9 +1809,9 @@ mod tests {
fn test_envelop_decode() {
// random tx: <https://etherscan.io/getRawTx?tx=0x9448608d36e721ef403c53b00546068a6474d6cbab6816c3926de449898e7bce>
let input = bytes!("02f871018302a90f808504890aef60826b6c94ddf4c5025d1a5742cf12f74eec246d4432c295e487e09c3bbcc12b2b80c080a0f21a4eacd0bf8fea9c5105c543be5a1d8c796516875710fafafdf16d16d8ee23a001280915021bb446d1973501a67f93d2b38894a514b976e7b46dc2fe54598d76");
let decoded = TransactionSigned::decode_enveloped(&mut input.as_ref()).unwrap();
let decoded = TransactionSigned::decode_2718(&mut input.as_ref()).unwrap();
let encoded = decoded.envelope_encoded();
let encoded = decoded.encoded_2718();
assert_eq!(encoded, input);
}
@ -2022,13 +1890,13 @@ mod tests {
#[test]
fn recover_enveloped() {
let data = hex!("02f86f0102843b9aca0085029e7822d68298f094d9e1459a7a482635700cbc20bbaf52d495ab9c9680841b55ba3ac080a0c199674fcb29f353693dd779c017823b954b3c69dffa3cd6b2a6ff7888798039a028ca912de909e7e6cdef9cdcaf24c54dd8c1032946dfa1d85c206b32a9064fe8");
let tx = TransactionSigned::decode_enveloped(&mut data.as_slice()).unwrap();
let tx = TransactionSigned::decode_2718(&mut data.as_slice()).unwrap();
let sender = tx.recover_signer().unwrap();
assert_eq!(sender, address!("001e2b7dE757bA469a57bF6b23d982458a07eFcE"));
assert_eq!(tx.to(), Some(address!("D9e1459A7A482635700cBc20BBAF52D495Ab9C96")));
assert_eq!(tx.input().as_ref(), hex!("1b55ba3a"));
let encoded = tx.envelope_encoded();
assert_eq!(encoded.as_ref(), data.as_slice());
let encoded = tx.encoded_2718();
assert_eq!(encoded.as_ref(), data.to_vec());
}
// <https://github.com/paradigmxyz/reth/issues/7750>
@ -2036,7 +1904,7 @@ mod tests {
#[test]
fn recover_pre_eip2() {
let data = hex!("f8ea0c850ba43b7400832dc6c0942935aa0a2d2fbb791622c29eb1c117b65b7a908580b884590528a9000000000000000000000001878ace42092b7f1ae1f28d16c1272b1aa80ca4670000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000d02ab486cedc0000000000000000000000000000000000000000000000000000557fe293cabc08cf1ca05bfaf3fda0a56b49cc78b22125feb5ae6a99d2b4781f00507d8b02c173771c85a0b5da0dbe6c5bc53740d0071fc83eb17ba0f709e49e9ae7df60dee625ef51afc5");
let tx = TransactionSigned::decode_enveloped(&mut data.as_slice()).unwrap();
let tx = TransactionSigned::decode_2718(&mut data.as_slice()).unwrap();
let sender = tx.recover_signer();
assert!(sender.is_none());
let sender = tx.recover_signer_unchecked().unwrap();
@ -2096,28 +1964,8 @@ mod tests {
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_enveloped(&mut &data[..]);
let res = TransactionSigned::decode_2718(&mut &data[..]);
assert!(res.is_err());
}
#[test]
fn decode_envelope_fails_on_trailing_bytes_legacy() {
let data = [201, 3, 56, 56, 128, 43, 36, 27, 128, 3, 192];
let result = TransactionSigned::decode_enveloped(&mut data.as_ref());
assert!(result.is_err());
assert_eq!(result, Err(RlpError::UnexpectedLength));
}
#[test]
fn decode_envelope_fails_on_trailing_bytes_eip2718() {
let data = hex!("02f872018307910d808507204d2cb1827d0094388c818ca8b9251b393131c08a736a67ccb19297880320d04823e2701c80c001a0cf024f4815304df2867a1a74e9d2707b6abda0337d2d54a4438d453f4160f190a07ac0e6b3bc9395b5b9c8b9e6d77204a236577a5b18467b9175c01de4faa208d900");
let result = TransactionSigned::decode_enveloped(&mut data.as_ref());
assert!(result.is_err());
assert_eq!(result, Err(RlpError::UnexpectedLength));
}
}

View File

@ -15,6 +15,7 @@ use alloy_consensus::{
transaction::{TxEip1559, TxEip2930, TxEip4844, TxLegacy},
SignableTransaction, TxEip4844WithSidecar,
};
use alloy_eips::eip2718::{Decodable2718, Eip2718Error};
use alloy_primitives::{Address, Bytes, TxHash, B256};
use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header, EMPTY_LIST_CODE};
use bytes::Buf;
@ -222,6 +223,9 @@ impl PooledTransactionsElement {
// decode the type byte, only decode BlobTransaction if it is a 4844 transaction
let tx_type = *data.first().ok_or(RlpError::InputTooShort)?;
// First, we advance the buffer past the type byte
data.advance(1);
if tx_type == EIP4844_TX_TYPE_ID {
// Recall that the blob transaction response `TransactionPayload` is encoded like
// this: `rlp([tx_payload_body, blobs, commitments, proofs])`
@ -231,18 +235,17 @@ impl PooledTransactionsElement {
//
// This makes the full encoding:
// `tx_type (0x03) || rlp([[chain_id, nonce, ...], blobs, commitments, proofs])`
//
// First, we advance the buffer past the type byte
data.advance(1);
// Now, we decode the inner blob transaction:
// `rlp([[chain_id, nonce, ...], blobs, commitments, proofs])`
let blob_tx = BlobTransaction::decode_inner(data)?;
Ok(Self::BlobTransaction(blob_tx))
} else {
// DO NOT advance the buffer for the type, since we want the enveloped decoding to
// decode it again and advance the buffer on its own.
let typed_tx = TransactionSigned::decode_enveloped_typed_transaction(data)?;
let typed_tx =
TransactionSigned::typed_decode(tx_type, data).map_err(|err| match err {
Eip2718Error::RlpError(err) => err,
_ => RlpError::Custom("failed to decode EIP-2718 transaction"),
})?;
// because we checked the tx type, we can be sure that the transaction is not a
// blob transaction or legacy
@ -337,7 +340,7 @@ impl PooledTransactionsElement {
/// Returns the enveloped encoded transactions.
///
/// See also [`TransactionSigned::encode_enveloped`]
/// See also [`alloy_eips::eip2718::Encodable2718::encoded_2718`]
pub fn envelope_encoded(&self) -> Bytes {
let mut buf = Vec::new();
self.encode_enveloped(&mut buf);
@ -591,6 +594,9 @@ impl Decodable for PooledTransactionsElement {
let tx_type = *buf.first().ok_or(RlpError::InputTooShort)?;
let remaining_len = buf.len();
// Aadvance the buffer past the type byte
buf.advance(1);
if tx_type == EIP4844_TX_TYPE_ID {
// Recall that the blob transaction response `TransactionPayload` is encoded like
// this: `rlp([tx_payload_body, blobs, commitments, proofs])`
@ -600,11 +606,8 @@ impl Decodable for PooledTransactionsElement {
//
// This makes the full encoding:
// `tx_type (0x03) || rlp([[chain_id, nonce, ...], blobs, commitments, proofs])`
//
// First, we advance the buffer past the type byte
buf.advance(1);
// Now, we decode the inner blob transaction:
// Decode the inner blob transaction:
// `rlp([[chain_id, nonce, ...], blobs, commitments, proofs])`
let blob_tx = BlobTransaction::decode_inner(buf)?;
@ -616,9 +619,8 @@ impl Decodable for PooledTransactionsElement {
Ok(Self::BlobTransaction(blob_tx))
} else {
// DO NOT advance the buffer for the type, since we want the enveloped decoding to
// decode it again and advance the buffer on its own.
let typed_tx = TransactionSigned::decode_enveloped_typed_transaction(buf)?;
let typed_tx =
TransactionSigned::typed_decode(tx_type, buf).map_err(RlpError::from)?;
// check that the bytes consumed match the payload length
let bytes_consumed = remaining_len - buf.len();

View File

@ -120,6 +120,7 @@ mod tests {
},
Signature,
};
use alloy_eips::eip2718::Decodable2718;
use alloy_primitives::{hex, Address, Parity, B256, U256};
use std::str::FromStr;
@ -164,7 +165,7 @@ mod tests {
//
// Block number: 46170
let raw_tx = hex!("f86d8085746a52880082520894c93f2250589a6563f5359051c1ea25746549f0d889208686e75e903bc000801ba034b6fdc33ea520e8123cf5ac4a9ff476f639cab68980cd9366ccae7aef437ea0a0e517caa5f50e27ca0d1e9a92c503b4ccb039680c6d9d0c71203ed611ea4feb33");
let tx = crate::transaction::TransactionSigned::decode_enveloped(&mut &raw_tx[..]).unwrap();
let tx = crate::transaction::TransactionSigned::decode_2718(&mut &raw_tx[..]).unwrap();
let signature = tx.signature();
// make sure we know it's greater than SECP256K1N_HALF

View File

@ -32,6 +32,7 @@ reth-network-api.workspace = true
reth-trie.workspace = true
# ethereum
alloy-eips.workspace = true
alloy-dyn-abi = { workspace = true, features = ["eip712"] }
alloy-json-rpc.workspace = true
alloy-network.workspace = true
@ -39,7 +40,6 @@ alloy-primitives.workspace = true
alloy-rpc-types-eth.workspace = true
alloy-rpc-types.workspace = true
alloy-rpc-types-mev.workspace = true
alloy-eips.workspace = true
# rpc
jsonrpsee = { workspace = true, features = ["server", "macros"] }

View File

@ -2,6 +2,7 @@
//! network.
use alloy_dyn_abi::TypedData;
use alloy_eips::eip2718::Encodable2718;
use alloy_network::TransactionBuilder;
use alloy_primitives::{Address, Bytes, TxHash, B256};
use alloy_rpc_types::{BlockNumberOrTag, TransactionInfo};
@ -106,7 +107,7 @@ pub trait EthTransactions: LoadTransaction {
Ok(LoadTransaction::provider(this)
.transaction_by_hash(hash)
.map_err(Self::Error::from_eth_err)?
.map(|tx| tx.envelope_encoded()))
.map(|tx| tx.encoded_2718().into()))
})
.await
}
@ -305,7 +306,7 @@ pub trait EthTransactions: LoadTransaction {
async move {
if let Some(block) = self.block_with_senders(block_id).await? {
if let Some(tx) = block.transactions().nth(index) {
return Ok(Some(tx.envelope_encoded()))
return Ok(Some(tx.encoded_2718().into()))
}
}

View File

@ -17,6 +17,7 @@ reth-primitives.workspace = true
reth-trie-common.workspace = true
# ethereum
alloy-eips.workspace = true
alloy-primitives.workspace = true
alloy-rlp.workspace = true
alloy-rpc-types.workspace = true

View File

@ -1,6 +1,7 @@
//! Standalone Conversion Functions for Handling Different Versions of Execution Payloads in
//! Ethereum's Engine
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
use alloy_primitives::{B256, U256};
use alloy_rpc_types_engine::{
payload::{ExecutionPayloadBodyV1, ExecutionPayloadFieldV2, ExecutionPayloadInputV2},
@ -26,7 +27,17 @@ pub fn try_payload_v1_to_block(payload: ExecutionPayloadV1) -> Result<Block, Pay
let transactions = payload
.transactions
.iter()
.map(|tx| TransactionSigned::decode_enveloped(&mut tx.as_ref()))
.map(|tx| {
let mut buf = tx.as_ref();
let tx = TransactionSigned::decode_2718(&mut buf).map_err(alloy_rlp::Error::from)?;
if !buf.is_empty() {
return Err(alloy_rlp::Error::UnexpectedLength);
}
Ok(tx)
})
.collect::<Result<Vec<_>, _>>()?;
let transactions_root = proofs::calculate_transaction_root(&transactions);
@ -360,7 +371,7 @@ pub fn validate_block_hash(
pub fn convert_to_payload_body_v1(value: Block) -> ExecutionPayloadBodyV1 {
let transactions = value.body.transactions.into_iter().map(|tx| {
let mut out = Vec::new();
tx.encode_enveloped(&mut out);
tx.encode_2718(&mut out);
out.into()
});
ExecutionPayloadBodyV1 {
@ -373,7 +384,7 @@ pub fn convert_to_payload_body_v1(value: Block) -> ExecutionPayloadBodyV1 {
pub fn convert_to_payload_body_v2(value: Block) -> ExecutionPayloadBodyV2 {
let transactions = value.body.transactions.into_iter().map(|tx| {
let mut out = Vec::new();
tx.encode_enveloped(&mut out);
tx.encode_2718(&mut out);
out.into()
});

View File

@ -39,6 +39,7 @@ reth-trie.workspace = true
alloy-consensus.workspace = true
alloy-signer.workspace = true
alloy-signer-local.workspace = true
alloy-eips.workspace = true
alloy-dyn-abi.workspace = true
alloy-genesis.workspace = true
alloy-network.workspace = true

View File

@ -1,3 +1,4 @@
use alloy_eips::eip2718::Encodable2718;
use alloy_primitives::{Address, Bytes, B256, U256};
use alloy_rlp::{Decodable, Encodable};
use alloy_rpc_types::{
@ -883,7 +884,7 @@ where
.block_with_senders_by_id(block_id, TransactionVariant::NoHash)
.to_rpc_result()?
.unwrap_or_default();
Ok(block.into_transactions_ecrecovered().map(|tx| tx.envelope_encoded()).collect())
Ok(block.into_transactions_ecrecovered().map(|tx| tx.encoded_2718().into()).collect())
}
/// Handler for `debug_getRawReceipts`

View File

@ -5,6 +5,7 @@ use std::collections::HashMap;
use crate::EthApi;
use alloy_consensus::TxEnvelope;
use alloy_dyn_abi::TypedData;
use alloy_eips::eip2718::Decodable2718;
use alloy_network::{eip2718::Encodable2718, EthereumWallet, TransactionBuilder};
use alloy_primitives::{eip191_hash_message, Address, B256};
use alloy_rpc_types_eth::TransactionRequest;
@ -95,7 +96,7 @@ impl EthSigner for DevSigner {
// decode transaction into signed transaction type
let encoded = txn_envelope.encoded_2718();
let txn_signed = TransactionSigned::decode_enveloped(&mut encoded.as_ref())
let txn_signed = TransactionSigned::decode_2718(&mut encoded.as_ref())
.map_err(|_| SignError::InvalidTransactionRequest)?;
Ok(txn_signed)

View File

@ -1,6 +1,6 @@
use crate::EthPooledTransaction;
use alloy_consensus::{TxEip1559, TxEip4844, TxLegacy};
use alloy_eips::eip2930::AccessList;
use alloy_eips::{eip2718::Encodable2718, eip2930::AccessList};
use alloy_primitives::{Address, Bytes, TxKind, B256, U256};
use rand::Rng;
use reth_chainspec::MAINNET;
@ -106,7 +106,7 @@ impl<R: Rng> TransactionGenerator<R> {
/// Generates and returns a pooled EIP-4844 transaction with a random signer.
pub fn gen_eip4844_pooled(&mut self) -> EthPooledTransaction {
let tx = self.gen_eip4844().into_ecrecovered().unwrap();
let encoded_length = tx.length_without_header();
let encoded_length = tx.encode_2718_len();
EthPooledTransaction::new(tx, encoded_length)
}
}

View File

@ -7,7 +7,7 @@ use crate::{
validate::ValidPoolTransaction,
AllTransactionsEvents,
};
use alloy_eips::{eip2930::AccessList, eip4844::BlobAndProofV1};
use alloy_eips::{eip2718::Encodable2718, eip2930::AccessList, eip4844::BlobAndProofV1};
use alloy_primitives::{Address, TxHash, TxKind, B256, U256};
use futures_util::{ready, Stream};
use reth_eth_wire_types::HandleMempoolData;
@ -1251,7 +1251,7 @@ impl TryFrom<TransactionSignedEcRecovered> for EthPooledTransaction {
}
};
let encoded_length = tx.length_without_header();
let encoded_length = tx.encode_2718_len();
let transaction = Self::new(tx, encoded_length);
Ok(transaction)
}