mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
eip2930: use alloy TxEip2930 (#10623)
This commit is contained in:
@ -113,10 +113,7 @@ impl TryFrom<WithOtherFields<alloy_rpc_types::Transaction>> for Transaction {
|
||||
Ok(Self::Eip2930(TxEip2930 {
|
||||
chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?,
|
||||
nonce: tx.nonce,
|
||||
gas_limit: tx
|
||||
.gas
|
||||
.try_into()
|
||||
.map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?,
|
||||
gas_limit: tx.gas,
|
||||
to: tx.to.map_or(TxKind::Create, TxKind::Call),
|
||||
value: tx.value,
|
||||
input: tx.input,
|
||||
|
||||
@ -36,7 +36,7 @@ impl FillTxEnv for TransactionSigned {
|
||||
tx_env.authorization_list = None;
|
||||
}
|
||||
Transaction::Eip2930(tx) => {
|
||||
tx_env.gas_limit = tx.gas_limit;
|
||||
tx_env.gas_limit = tx.gas_limit as u64;
|
||||
tx_env.gas_price = U256::from(tx.gas_price);
|
||||
tx_env.gas_priority_fee = None;
|
||||
tx_env.transact_to = tx.to;
|
||||
|
||||
@ -1,262 +1 @@
|
||||
use super::access_list::AccessList;
|
||||
use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256};
|
||||
use alloy_rlp::{length_of_length, Decodable, Encodable, Header};
|
||||
use core::mem;
|
||||
|
||||
#[cfg(any(test, feature = "reth-codec"))]
|
||||
use reth_codecs::Compact;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Transaction with an [`AccessList`] ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(any(test, feature = "reth-codec"), derive(Compact))]
|
||||
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
|
||||
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
|
||||
pub struct TxEip2930 {
|
||||
/// Added as EIP-155: Simple replay attack protection
|
||||
pub chain_id: ChainId,
|
||||
|
||||
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
|
||||
pub nonce: u64,
|
||||
|
||||
/// A scalar value equal to the number of
|
||||
/// Wei to be paid per unit of gas for all computation
|
||||
/// costs incurred as a result of the execution of this transaction; formally Tp.
|
||||
///
|
||||
/// As ethereum circulation is around 120mil eth as of 2022 that is around
|
||||
/// 120000000000000000000000000 wei we are safe to use u128 as its max number is:
|
||||
/// 340282366920938463463374607431768211455
|
||||
pub gas_price: u128,
|
||||
|
||||
/// A scalar value equal to the maximum
|
||||
/// amount of gas that should be used in executing
|
||||
/// this transaction. This is paid up-front, before any
|
||||
/// computation is done and may not be increased
|
||||
/// later; formally Tg.
|
||||
pub gas_limit: u64,
|
||||
|
||||
/// The 160-bit address of the message call’s recipient or, for a contract creation
|
||||
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
|
||||
pub to: TxKind,
|
||||
|
||||
/// A scalar value equal to the number of Wei to
|
||||
/// be transferred to the message call’s recipient or,
|
||||
/// in the case of contract creation, as an endowment
|
||||
/// to the newly created account; formally Tv.
|
||||
pub value: U256,
|
||||
|
||||
/// The accessList specifies a list of addresses and storage keys;
|
||||
/// these addresses and storage keys are added into the `accessed_addresses`
|
||||
/// and `accessed_storage_keys` global sets (introduced in EIP-2929).
|
||||
/// A gas cost is charged, though at a discount relative to the cost of
|
||||
/// accessing outside the list.
|
||||
pub access_list: AccessList,
|
||||
|
||||
/// Input has two uses depending if the transaction `to` field is [`TxKind::Create`] or
|
||||
/// [`TxKind::Call`].
|
||||
///
|
||||
/// Input as init code, or if `to` is [`TxKind::Create`]: An unlimited size byte array
|
||||
/// specifying the EVM-code for the account initialisation procedure `CREATE`
|
||||
///
|
||||
/// Input as data, or if `to` is [`TxKind::Call`]: An unlimited size byte array specifying the
|
||||
/// input data of the message call, formally Td.
|
||||
pub input: Bytes,
|
||||
}
|
||||
|
||||
impl TxEip2930 {
|
||||
/// Calculates a heuristic for the in-memory size of the [`TxEip2930`] transaction.
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
mem::size_of::<ChainId>() + // chain_id
|
||||
mem::size_of::<u64>() + // nonce
|
||||
mem::size_of::<u128>() + // gas_price
|
||||
mem::size_of::<u64>() + // gas_limit
|
||||
self.to.size() + // to
|
||||
mem::size_of::<U256>() + // value
|
||||
self.access_list.size() + // access_list
|
||||
self.input.len() // input
|
||||
}
|
||||
|
||||
/// Decodes the inner [`TxEip2930`] fields from RLP bytes.
|
||||
///
|
||||
/// NOTE: This assumes a RLP header has already been decoded, and _just_ decodes the following
|
||||
/// RLP fields in the following order:
|
||||
///
|
||||
/// - `chain_id`
|
||||
/// - `nonce`
|
||||
/// - `gas_price`
|
||||
/// - `gas_limit`
|
||||
/// - `to`
|
||||
/// - `value`
|
||||
/// - `data` (`input`)
|
||||
/// - `access_list`
|
||||
pub(crate) fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
Ok(Self {
|
||||
chain_id: Decodable::decode(buf)?,
|
||||
nonce: Decodable::decode(buf)?,
|
||||
gas_price: Decodable::decode(buf)?,
|
||||
gas_limit: Decodable::decode(buf)?,
|
||||
to: Decodable::decode(buf)?,
|
||||
value: Decodable::decode(buf)?,
|
||||
input: Decodable::decode(buf)?,
|
||||
access_list: Decodable::decode(buf)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Outputs the length of the transaction's fields, without a RLP header.
|
||||
pub(crate) fn fields_len(&self) -> usize {
|
||||
self.chain_id.length() +
|
||||
self.nonce.length() +
|
||||
self.gas_price.length() +
|
||||
self.gas_limit.length() +
|
||||
self.to.length() +
|
||||
self.value.length() +
|
||||
self.input.0.length() +
|
||||
self.access_list.length()
|
||||
}
|
||||
|
||||
/// Encodes only the transaction's fields into the desired buffer, without a RLP header.
|
||||
pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) {
|
||||
self.chain_id.encode(out);
|
||||
self.nonce.encode(out);
|
||||
self.gas_price.encode(out);
|
||||
self.gas_limit.encode(out);
|
||||
self.to.encode(out);
|
||||
self.value.encode(out);
|
||||
self.input.0.encode(out);
|
||||
self.access_list.encode(out);
|
||||
}
|
||||
|
||||
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
|
||||
/// hash that for eip2718 does not require rlp header
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `rlp(nonce, gas_price, gas_limit, to, value, input, access_list, y_parity, r, s)`
|
||||
pub(crate) fn encode_with_signature(
|
||||
&self,
|
||||
signature: &Signature,
|
||||
out: &mut dyn bytes::BufMut,
|
||||
with_header: bool,
|
||||
) {
|
||||
let payload_length = self.fields_len() + signature.payload_len();
|
||||
if with_header {
|
||||
Header {
|
||||
list: false,
|
||||
payload_length: 1 + length_of_length(payload_length) + payload_length,
|
||||
}
|
||||
.encode(out);
|
||||
}
|
||||
out.put_u8(self.tx_type() as u8);
|
||||
let header = Header { list: true, payload_length };
|
||||
header.encode(out);
|
||||
self.encode_fields(out);
|
||||
signature.encode(out);
|
||||
}
|
||||
|
||||
/// Output the length of the RLP signed transaction encoding, _without_ a RLP string header.
|
||||
pub(crate) fn payload_len_with_signature_without_header(&self, signature: &Signature) -> usize {
|
||||
let payload_length = self.fields_len() + signature.payload_len();
|
||||
// 'transaction type byte length' + 'header length' + 'payload length'
|
||||
1 + length_of_length(payload_length) + payload_length
|
||||
}
|
||||
|
||||
/// Output the length of the RLP signed transaction encoding. This encodes with a RLP header.
|
||||
pub(crate) fn payload_len_with_signature(&self, signature: &Signature) -> usize {
|
||||
let len = self.payload_len_with_signature_without_header(signature);
|
||||
length_of_length(len) + len
|
||||
}
|
||||
|
||||
/// Get transaction type
|
||||
pub(crate) const fn tx_type(&self) -> TxType {
|
||||
TxType::Eip2930
|
||||
}
|
||||
|
||||
/// Encodes the EIP-2930 transaction in RLP for signing.
|
||||
///
|
||||
/// This encodes the transaction as:
|
||||
/// `tx_type || rlp(chain_id, nonce, gas_price, gas_limit, to, value, input, access_list)`
|
||||
///
|
||||
/// Note that there is no rlp header before the transaction type byte.
|
||||
pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
|
||||
out.put_u8(self.tx_type() as u8);
|
||||
Header { list: true, payload_length: self.fields_len() }.encode(out);
|
||||
self.encode_fields(out);
|
||||
}
|
||||
|
||||
/// Outputs the length of the signature RLP encoding for the transaction.
|
||||
pub(crate) fn payload_len_for_signature(&self) -> usize {
|
||||
let payload_length = self.fields_len();
|
||||
// 'transaction type byte length' + 'header length' + 'payload length'
|
||||
1 + length_of_length(payload_length) + payload_length
|
||||
}
|
||||
|
||||
/// Outputs the signature hash of the transaction by first encoding without a signature, then
|
||||
/// hashing.
|
||||
pub(crate) fn signature_hash(&self) -> B256 {
|
||||
let mut buf = Vec::with_capacity(self.payload_len_for_signature());
|
||||
self.encode_for_signing(&mut buf);
|
||||
keccak256(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::TxEip2930;
|
||||
use crate::{
|
||||
transaction::{signature::Signature, TxKind},
|
||||
Address, Bytes, Transaction, TransactionSigned, U256,
|
||||
};
|
||||
use alloy_rlp::{Decodable, Encodable};
|
||||
|
||||
#[test]
|
||||
fn test_decode_create() {
|
||||
// tests that a contract creation tx encodes and decodes properly
|
||||
let request = Transaction::Eip2930(TxEip2930 {
|
||||
chain_id: 1u64,
|
||||
nonce: 0,
|
||||
gas_price: 1,
|
||||
gas_limit: 2,
|
||||
to: TxKind::Create,
|
||||
value: U256::from(3),
|
||||
input: Bytes::from(vec![1, 2]),
|
||||
access_list: Default::default(),
|
||||
});
|
||||
let signature = Signature { odd_y_parity: true, r: U256::default(), s: U256::default() };
|
||||
let tx = TransactionSigned::from_transaction_and_signature(request, signature);
|
||||
|
||||
let mut encoded = Vec::new();
|
||||
tx.encode(&mut encoded);
|
||||
assert_eq!(encoded.len(), tx.length());
|
||||
|
||||
let decoded = TransactionSigned::decode(&mut &*encoded).unwrap();
|
||||
assert_eq!(decoded, tx);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_call() {
|
||||
let request = Transaction::Eip2930(TxEip2930 {
|
||||
chain_id: 1u64,
|
||||
nonce: 0,
|
||||
gas_price: 1,
|
||||
gas_limit: 2,
|
||||
to: Address::default().into(),
|
||||
value: U256::from(3),
|
||||
input: Bytes::from(vec![1, 2]),
|
||||
access_list: Default::default(),
|
||||
});
|
||||
|
||||
let signature = Signature { odd_y_parity: true, r: U256::default(), s: U256::default() };
|
||||
|
||||
let tx = TransactionSigned::from_transaction_and_signature(request, signature);
|
||||
|
||||
let mut encoded = Vec::new();
|
||||
tx.encode(&mut encoded);
|
||||
assert_eq!(encoded.len(), tx.length());
|
||||
|
||||
let decoded = TransactionSigned::decode(&mut &*encoded).unwrap();
|
||||
assert_eq!(decoded, tx);
|
||||
}
|
||||
}
|
||||
pub use alloy_consensus::transaction::TxEip2930;
|
||||
|
||||
@ -143,27 +143,27 @@ pub enum Transaction {
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> arbitrary::Arbitrary<'a> for Transaction {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
let mut tx = match TxType::arbitrary(u)? {
|
||||
TxType::Legacy => Self::Legacy(TxLegacy::arbitrary(u)?),
|
||||
TxType::Eip2930 => Self::Eip2930(TxEip2930::arbitrary(u)?),
|
||||
TxType::Eip1559 => Self::Eip1559(TxEip1559::arbitrary(u)?),
|
||||
Ok(match TxType::arbitrary(u)? {
|
||||
TxType::Legacy => {
|
||||
let mut tx = TxLegacy::arbitrary(u)?;
|
||||
tx.gas_limit = (tx.gas_limit as u64).into();
|
||||
Self::Legacy(tx)
|
||||
}
|
||||
TxType::Eip2930 => {
|
||||
let mut tx = TxEip2930::arbitrary(u)?;
|
||||
tx.gas_limit = (tx.gas_limit as u64).into();
|
||||
Self::Eip2930(tx)
|
||||
}
|
||||
TxType::Eip1559 => {
|
||||
let mut tx = TxEip1559::arbitrary(u)?;
|
||||
tx.gas_limit = (tx.gas_limit as u64).into();
|
||||
Self::Eip1559(tx)
|
||||
}
|
||||
TxType::Eip4844 => Self::Eip4844(TxEip4844::arbitrary(u)?),
|
||||
TxType::Eip7702 => Self::Eip7702(TxEip7702::arbitrary(u)?),
|
||||
#[cfg(feature = "optimism")]
|
||||
TxType::Deposit => Self::Deposit(TxDeposit::arbitrary(u)?),
|
||||
};
|
||||
|
||||
match &mut tx {
|
||||
Self::Legacy(tx) => {
|
||||
tx.gas_limit = (tx.gas_limit as u64).into();
|
||||
}
|
||||
Self::Eip1559(tx) => {
|
||||
tx.gas_limit = (tx.gas_limit as u64).into();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(tx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ impl Transaction {
|
||||
pub const fn tx_type(&self) -> TxType {
|
||||
match self {
|
||||
Self::Legacy(_) => TxType::Legacy,
|
||||
Self::Eip2930(access_list_tx) => access_list_tx.tx_type(),
|
||||
Self::Eip2930(_) => TxType::Eip2930,
|
||||
Self::Eip1559(_) => TxType::Eip1559,
|
||||
Self::Eip4844(blob_tx) => blob_tx.tx_type(),
|
||||
Self::Eip7702(set_code_tx) => set_code_tx.tx_type(),
|
||||
@ -300,11 +300,11 @@ impl Transaction {
|
||||
/// Get the gas limit of the transaction.
|
||||
pub const fn gas_limit(&self) -> u64 {
|
||||
match self {
|
||||
Self::Legacy(TxLegacy { gas_limit, .. }) |
|
||||
Self::Legacy(TxLegacy { gas_limit, .. }) => *gas_limit as u64,
|
||||
Self::Eip1559(TxEip1559 { gas_limit, .. }) => *gas_limit as u64,
|
||||
Self::Eip2930(TxEip2930 { gas_limit, .. }) |
|
||||
Self::Eip4844(TxEip4844 { gas_limit, .. }) |
|
||||
Self::Eip7702(TxEip7702 { gas_limit, .. }) => *gas_limit,
|
||||
Self::Eip2930(TxEip2930 { gas_limit, .. }) => *gas_limit as u64,
|
||||
#[cfg(feature = "optimism")]
|
||||
Self::Deposit(TxDeposit { gas_limit, .. }) => *gas_limit,
|
||||
}
|
||||
@ -526,9 +526,11 @@ impl Transaction {
|
||||
out,
|
||||
)
|
||||
}
|
||||
Self::Eip2930(access_list_tx) => {
|
||||
access_list_tx.encode_with_signature(signature, out, with_header)
|
||||
}
|
||||
Self::Eip2930(access_list_tx) => access_list_tx.encode_with_signature(
|
||||
&signature.as_signature_with_boolean_parity(),
|
||||
out,
|
||||
with_header,
|
||||
),
|
||||
Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encode_with_signature(
|
||||
&signature.as_signature_with_boolean_parity(),
|
||||
out,
|
||||
@ -547,7 +549,7 @@ impl Transaction {
|
||||
pub fn set_gas_limit(&mut self, gas_limit: u64) {
|
||||
match self {
|
||||
Self::Legacy(tx) => tx.gas_limit = gas_limit.into(),
|
||||
Self::Eip2930(tx) => tx.gas_limit = gas_limit,
|
||||
Self::Eip2930(tx) => tx.gas_limit = gas_limit.into(),
|
||||
Self::Eip1559(tx) => tx.gas_limit = gas_limit.into(),
|
||||
Self::Eip4844(tx) => tx.gas_limit = gas_limit,
|
||||
Self::Eip7702(tx) => tx.gas_limit = gas_limit,
|
||||
@ -1209,9 +1211,10 @@ impl TransactionSigned {
|
||||
Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature(
|
||||
&self.signature.as_signature_with_eip155_parity(legacy_tx.chain_id),
|
||||
),
|
||||
Transaction::Eip2930(access_list_tx) => {
|
||||
access_list_tx.payload_len_with_signature(&self.signature)
|
||||
}
|
||||
Transaction::Eip2930(access_list_tx) => access_list_tx.encoded_len_with_signature(
|
||||
&self.signature.as_signature_with_boolean_parity(),
|
||||
true,
|
||||
),
|
||||
Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature(
|
||||
&self.signature.as_signature_with_boolean_parity(),
|
||||
true,
|
||||
@ -1343,7 +1346,7 @@ impl TransactionSigned {
|
||||
};
|
||||
|
||||
let transaction = match tx_type {
|
||||
TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_inner(data)?),
|
||||
TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_fields(data)?),
|
||||
TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_fields(data)?),
|
||||
TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_inner(data)?),
|
||||
TxType::Eip7702 => Transaction::Eip7702(TxEip7702::decode_inner(data)?),
|
||||
@ -1416,9 +1419,10 @@ impl TransactionSigned {
|
||||
Transaction::Legacy(legacy_tx) => legacy_tx.encoded_len_with_signature(
|
||||
&self.signature.as_signature_with_eip155_parity(legacy_tx.chain_id),
|
||||
),
|
||||
Transaction::Eip2930(access_list_tx) => {
|
||||
access_list_tx.payload_len_with_signature_without_header(&self.signature)
|
||||
}
|
||||
Transaction::Eip2930(access_list_tx) => access_list_tx.encoded_len_with_signature(
|
||||
&self.signature.as_signature_with_boolean_parity(),
|
||||
false,
|
||||
),
|
||||
Transaction::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.encoded_len_with_signature(
|
||||
&self.signature.as_signature_with_boolean_parity(),
|
||||
false,
|
||||
|
||||
@ -308,7 +308,10 @@ impl PooledTransactionsElement {
|
||||
}
|
||||
Self::Eip2930 { transaction, signature, .. } => {
|
||||
// method computes the payload len without a RLP header
|
||||
transaction.payload_len_with_signature_without_header(signature)
|
||||
transaction.encoded_len_with_signature(
|
||||
&signature.as_signature_with_boolean_parity(),
|
||||
false,
|
||||
)
|
||||
}
|
||||
Self::Eip1559 { transaction, signature, .. } => {
|
||||
// method computes the payload len without a RLP header
|
||||
@ -358,9 +361,11 @@ impl PooledTransactionsElement {
|
||||
&signature.as_signature_with_eip155_parity(transaction.chain_id),
|
||||
out,
|
||||
),
|
||||
Self::Eip2930 { transaction, signature, .. } => {
|
||||
transaction.encode_with_signature(signature, out, false)
|
||||
}
|
||||
Self::Eip2930 { transaction, signature, .. } => transaction.encode_with_signature(
|
||||
&signature.as_signature_with_boolean_parity(),
|
||||
out,
|
||||
false,
|
||||
),
|
||||
Self::Eip1559 { transaction, signature, .. } => transaction.encode_with_signature(
|
||||
&signature.as_signature_with_boolean_parity(),
|
||||
out,
|
||||
@ -495,7 +500,11 @@ impl Encodable for PooledTransactionsElement {
|
||||
),
|
||||
Self::Eip2930 { transaction, signature, .. } => {
|
||||
// encodes with string header
|
||||
transaction.encode_with_signature(signature, out, true)
|
||||
transaction.encode_with_signature(
|
||||
&signature.as_signature_with_boolean_parity(),
|
||||
out,
|
||||
true,
|
||||
)
|
||||
}
|
||||
Self::Eip1559 { transaction, signature, .. } => {
|
||||
// encodes with string header
|
||||
@ -528,7 +537,8 @@ impl Encodable for PooledTransactionsElement {
|
||||
}
|
||||
Self::Eip2930 { transaction, signature, .. } => {
|
||||
// method computes the payload len with a RLP header
|
||||
transaction.payload_len_with_signature(signature)
|
||||
transaction
|
||||
.encoded_len_with_signature(&signature.as_signature_with_boolean_parity(), true)
|
||||
}
|
||||
Self::Eip1559 { transaction, signature, .. } => {
|
||||
// method computes the payload len with a RLP header
|
||||
|
||||
62
crates/storage/codecs/src/alloy/transaction/eip2930.rs
Normal file
62
crates/storage/codecs/src/alloy/transaction/eip2930.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use crate::Compact;
|
||||
use alloy_consensus::transaction::TxEip2930 as AlloyTxEip2930;
|
||||
use alloy_eips::eip2930::AccessList;
|
||||
use alloy_primitives::{Bytes, ChainId, TxKind, U256};
|
||||
use reth_codecs_derive::add_arbitrary_tests;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Transaction with an [`AccessList`] ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)).
|
||||
///
|
||||
/// This is a helper type to use derive on it instead of manually managing `bitfield`.
|
||||
///
|
||||
/// By deriving `Compact` here, any future changes or enhancements to the `Compact` derive
|
||||
/// will automatically apply to this type.
|
||||
///
|
||||
/// Notice: Make sure this struct is 1:1 with [`alloy_consensus::transaction::TxEip2930`]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize, Compact)]
|
||||
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
|
||||
#[add_arbitrary_tests(compact)]
|
||||
pub(crate) struct TxEip2930 {
|
||||
chain_id: ChainId,
|
||||
nonce: u64,
|
||||
gas_price: u128,
|
||||
gas_limit: u64,
|
||||
to: TxKind,
|
||||
value: U256,
|
||||
access_list: AccessList,
|
||||
input: Bytes,
|
||||
}
|
||||
|
||||
impl Compact for AlloyTxEip2930 {
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
B: bytes::BufMut + AsMut<[u8]>,
|
||||
{
|
||||
let tx = TxEip2930 {
|
||||
chain_id: self.chain_id,
|
||||
nonce: self.nonce,
|
||||
gas_price: self.gas_price,
|
||||
gas_limit: self.gas_limit as u64,
|
||||
to: self.to,
|
||||
value: self.value,
|
||||
access_list: self.access_list.clone(),
|
||||
input: self.input.clone(),
|
||||
};
|
||||
tx.to_compact(buf)
|
||||
}
|
||||
|
||||
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
|
||||
let (tx, _) = TxEip2930::from_compact(buf, len);
|
||||
let alloy_tx = Self {
|
||||
chain_id: tx.chain_id,
|
||||
nonce: tx.nonce,
|
||||
gas_price: tx.gas_price,
|
||||
gas_limit: tx.gas_limit as u128,
|
||||
to: tx.to,
|
||||
value: tx.value,
|
||||
access_list: tx.access_list,
|
||||
input: tx.input,
|
||||
};
|
||||
(alloy_tx, buf)
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
mod eip1559;
|
||||
mod eip2930;
|
||||
mod legacy;
|
||||
|
||||
#[cfg(test)]
|
||||
@ -10,11 +11,12 @@ mod tests {
|
||||
// this check is to ensure we do not inadvertently add too many fields to a struct which would
|
||||
// expand the flags field and break backwards compatibility
|
||||
|
||||
use super::{eip1559::TxEip1559, legacy::TxLegacy};
|
||||
use super::{eip1559::TxEip1559, eip2930::TxEip2930, legacy::TxLegacy};
|
||||
|
||||
#[test]
|
||||
fn test_ensure_backwards_compatibility() {
|
||||
assert_eq!(TxLegacy::bitflag_encoded_bytes(), 3);
|
||||
assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4);
|
||||
assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion));
|
||||
mod tests {
|
||||
use super::*;
|
||||
use reth_primitives::{
|
||||
Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip2930, TxEip4844, Withdrawals,
|
||||
Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip4844, Withdrawals,
|
||||
};
|
||||
use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment};
|
||||
use reth_stages_types::{
|
||||
@ -342,7 +342,6 @@ mod tests {
|
||||
assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0);
|
||||
assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0);
|
||||
assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
|
||||
assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3);
|
||||
assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5);
|
||||
assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0);
|
||||
}
|
||||
@ -373,7 +372,6 @@ mod tests {
|
||||
assert_eq!(StoredBlockOmmers::bitflag_encoded_bytes(), 0);
|
||||
assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0);
|
||||
assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
|
||||
assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3);
|
||||
assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5);
|
||||
assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0);
|
||||
}
|
||||
|
||||
@ -819,7 +819,7 @@ impl TryFrom<TransactionSignedEcRecovered> for MockTransaction {
|
||||
sender,
|
||||
nonce,
|
||||
gas_price,
|
||||
gas_limit,
|
||||
gas_limit: gas_limit as u64,
|
||||
to,
|
||||
value,
|
||||
input,
|
||||
@ -944,7 +944,7 @@ impl From<MockTransaction> for Transaction {
|
||||
chain_id,
|
||||
nonce,
|
||||
gas_price,
|
||||
gas_limit,
|
||||
gas_limit: gas_limit.into(),
|
||||
to,
|
||||
value,
|
||||
access_list,
|
||||
@ -1053,7 +1053,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction {
|
||||
hash: tx_hash,
|
||||
nonce: *nonce,
|
||||
gas_price: *gas_price,
|
||||
gas_limit: *gas_limit,
|
||||
gas_limit: *gas_limit as u64,
|
||||
to: *to,
|
||||
value: *value,
|
||||
input: input.clone(),
|
||||
|
||||
Reference in New Issue
Block a user