chore: remove OpTxType new type (#12715)

This commit is contained in:
Matthias Seitz
2024-12-02 14:24:21 +01:00
committed by GitHub
parent dd055a4615
commit 519a10ae99
7 changed files with 118 additions and 296 deletions

2
Cargo.lock generated
View File

@ -8461,7 +8461,6 @@ dependencies = [
"alloy-consensus", "alloy-consensus",
"alloy-eips", "alloy-eips",
"alloy-primitives", "alloy-primitives",
"alloy-rlp",
"arbitrary", "arbitrary",
"bytes", "bytes",
"derive_more 1.0.0", "derive_more 1.0.0",
@ -8664,6 +8663,7 @@ dependencies = [
"bytes", "bytes",
"derive_more 1.0.0", "derive_more 1.0.0",
"modular-bitfield", "modular-bitfield",
"op-alloy-consensus",
"proptest", "proptest",
"proptest-arbitrary-interop", "proptest-arbitrary-interop",
"rand 0.8.5", "rand 0.8.5",

View File

@ -14,14 +14,13 @@ workspace = true
[dependencies] [dependencies]
# reth # reth
reth-primitives.workspace = true reth-primitives.workspace = true
reth-primitives-traits.workspace = true reth-primitives-traits = { workspace = true, features = ["op"] }
reth-codecs = { workspace = true, optional = true, features = ["optimism"] } reth-codecs = { workspace = true, optional = true, features = ["optimism"] }
# ethereum # ethereum
alloy-primitives.workspace = true alloy-primitives.workspace = true
alloy-consensus.workspace = true alloy-consensus.workspace = true
alloy-eips.workspace = true alloy-eips.workspace = true
alloy-rlp.workspace = true
# op # op
op-alloy-consensus.workspace = true op-alloy-consensus.workspace = true
@ -37,7 +36,7 @@ derive_more.workspace = true
arbitrary = { workspace = true, features = ["derive"], optional = true } arbitrary = { workspace = true, features = ["derive"], optional = true }
[dev-dependencies] [dev-dependencies]
reth-codecs = { workspace = true, features = ["test-utils"] } reth-codecs = { workspace = true, features = ["test-utils", "optimism"] }
rstest.workspace = true rstest.workspace = true
arbitrary.workspace = true arbitrary.workspace = true
@ -51,12 +50,13 @@ std = [
"alloy-eips/std", "alloy-eips/std",
"alloy-primitives/std", "alloy-primitives/std",
"serde/std", "serde/std",
"alloy-rlp/std"
] ]
reth-codec = [ reth-codec = [
"dep:reth-codecs", "dep:reth-codecs",
"reth-primitives/reth-codec", "reth-primitives/reth-codec",
"reth-primitives-traits/reth-codec", "reth-primitives-traits/reth-codec",
"reth-codecs?/optimism",
"reth-primitives/reth-codec"
] ]
serde = [ serde = [
"dep:serde", "dep:serde",

View File

@ -1,286 +1,21 @@
//! newtype pattern on `op_alloy_consensus::OpTxType`. //! Optimism transaction type.
//! `OpTxType` implements `reth_primitives_traits::TxType`.
//! This type is required because a `Compact` impl is needed on the deposit tx type.
use core::fmt::Debug; pub use op_alloy_consensus::OpTxType;
use alloy_primitives::{U64, U8};
use alloy_rlp::{Decodable, Encodable, Error};
use bytes::BufMut;
use derive_more::{
derive::{From, Into},
Display,
};
use op_alloy_consensus::OpTxType as AlloyOpTxType;
use reth_primitives_traits::{InMemorySize, TxType};
/// Wrapper type for [`op_alloy_consensus::OpTxType`] to implement
/// [`TxType`] trait.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Display, Ord, Hash, From, Into)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[into(u8)]
pub struct OpTxType(AlloyOpTxType);
impl TxType for OpTxType {
#[inline]
fn is_legacy(&self) -> bool {
matches!(self.0, AlloyOpTxType::Legacy)
}
#[inline]
fn is_eip2930(&self) -> bool {
matches!(self.0, AlloyOpTxType::Eip2930)
}
#[inline]
fn is_eip1559(&self) -> bool {
matches!(self.0, AlloyOpTxType::Eip1559)
}
#[inline]
fn is_eip4844(&self) -> bool {
false
}
#[inline]
fn is_eip7702(&self) -> bool {
matches!(self.0, AlloyOpTxType::Eip7702)
}
}
impl InMemorySize for OpTxType {
/// Calculates a heuristic for the in-memory size of the [`OpTxType`].
#[inline]
fn size(&self) -> usize {
core::mem::size_of::<Self>()
}
}
impl From<OpTxType> for U8 {
fn from(tx_type: OpTxType) -> Self {
Self::from(u8::from(tx_type))
}
}
impl TryFrom<u8> for OpTxType {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
AlloyOpTxType::try_from(value)
.map(OpTxType)
.map_err(|_| Error::Custom("Invalid transaction type"))
}
}
impl Default for OpTxType {
fn default() -> Self {
Self(AlloyOpTxType::Legacy)
}
}
impl PartialEq<u8> for OpTxType {
fn eq(&self, other: &u8) -> bool {
let self_as_u8: u8 = (*self).into();
&self_as_u8 == other
}
}
impl TryFrom<u64> for OpTxType {
type Error = Error;
fn try_from(value: u64) -> Result<Self, Self::Error> {
if value > u8::MAX as u64 {
return Err(Error::Custom("value out of range"));
}
Self::try_from(value as u8)
}
}
impl TryFrom<U64> for OpTxType {
type Error = Error;
fn try_from(value: U64) -> Result<Self, Self::Error> {
let u64_value: u64 = value.try_into().map_err(|_| Error::Custom("value out of range"))?;
Self::try_from(u64_value)
}
}
impl Encodable for OpTxType {
fn length(&self) -> usize {
let value: u8 = (*self).into();
value.length()
}
fn encode(&self, out: &mut dyn BufMut) {
let value: u8 = (*self).into();
value.encode(out);
}
}
impl Decodable for OpTxType {
fn decode(buf: &mut &[u8]) -> Result<Self, alloy_rlp::Error> {
// Decode the u8 value from RLP
let value = if buf.is_empty() {
return Err(alloy_rlp::Error::InputTooShort);
} else if buf[0] == 0x80 {
0 // Special case: RLP encoding for integer 0 is `b"\x80"`
} else {
u8::decode(buf)?
};
Self::try_from(value).map_err(|_| alloy_rlp::Error::Custom("Invalid transaction type"))
}
}
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for OpTxType {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
use reth_codecs::txtype::*;
match self.0 {
AlloyOpTxType::Legacy => COMPACT_IDENTIFIER_LEGACY,
AlloyOpTxType::Eip2930 => COMPACT_IDENTIFIER_EIP2930,
AlloyOpTxType::Eip1559 => COMPACT_IDENTIFIER_EIP1559,
AlloyOpTxType::Eip7702 => {
buf.put_u8(alloy_consensus::constants::EIP7702_TX_TYPE_ID);
COMPACT_EXTENDED_IDENTIFIER_FLAG
}
AlloyOpTxType::Deposit => {
buf.put_u8(op_alloy_consensus::DEPOSIT_TX_TYPE_ID);
COMPACT_EXTENDED_IDENTIFIER_FLAG
}
}
}
fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
use bytes::Buf;
(
match identifier {
reth_codecs::txtype::COMPACT_IDENTIFIER_LEGACY => Self(AlloyOpTxType::Legacy),
reth_codecs::txtype::COMPACT_IDENTIFIER_EIP2930 => Self(AlloyOpTxType::Eip2930),
reth_codecs::txtype::COMPACT_IDENTIFIER_EIP1559 => Self(AlloyOpTxType::Eip1559),
reth_codecs::txtype::COMPACT_EXTENDED_IDENTIFIER_FLAG => {
let extended_identifier = buf.get_u8();
match extended_identifier {
alloy_consensus::constants::EIP7702_TX_TYPE_ID => {
Self(AlloyOpTxType::Eip7702)
}
op_alloy_consensus::DEPOSIT_TX_TYPE_ID => Self(AlloyOpTxType::Deposit),
_ => panic!("Unsupported OpTxType identifier: {extended_identifier}"),
}
}
_ => panic!("Unknown identifier for OpTxType: {identifier}"),
},
buf,
)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use alloy_consensus::constants::EIP7702_TX_TYPE_ID; use alloy_consensus::constants::EIP7702_TX_TYPE_ID;
use bytes::BytesMut;
use op_alloy_consensus::DEPOSIT_TX_TYPE_ID; use op_alloy_consensus::DEPOSIT_TX_TYPE_ID;
use reth_codecs::{txtype::*, Compact}; use reth_codecs::{txtype::*, Compact};
use rstest::rstest; use rstest::rstest;
#[test]
fn test_from_alloy_op_tx_type() {
let alloy_tx = AlloyOpTxType::Legacy;
let op_tx: OpTxType = OpTxType::from(alloy_tx);
assert_eq!(op_tx, OpTxType(AlloyOpTxType::Legacy));
}
#[test]
fn test_from_op_tx_type_to_u8() {
let op_tx = OpTxType(AlloyOpTxType::Legacy);
let tx_type_u8: u8 = op_tx.into();
assert_eq!(tx_type_u8, AlloyOpTxType::Legacy as u8);
}
#[test]
fn test_from_op_tx_type_to_u8_u8() {
let op_tx = OpTxType(AlloyOpTxType::Legacy);
let tx_type_u8: U8 = op_tx.into();
assert_eq!(tx_type_u8, U8::from(AlloyOpTxType::Legacy as u8));
}
#[test]
fn test_try_from_u8() {
let op_tx = OpTxType::try_from(AlloyOpTxType::Legacy as u8).unwrap();
assert_eq!(op_tx, OpTxType(AlloyOpTxType::Legacy));
}
#[test]
fn test_try_from_invalid_u8() {
let invalid_value: u8 = 255;
let result = OpTxType::try_from(invalid_value);
assert_eq!(result, Err(Error::Custom("Invalid transaction type")));
}
#[test]
fn test_try_from_u64() {
let op_tx = OpTxType::try_from(AlloyOpTxType::Legacy as u64).unwrap();
assert_eq!(op_tx, OpTxType(AlloyOpTxType::Legacy));
}
#[test]
fn test_try_from_u64_out_of_range() {
let result = OpTxType::try_from(u64::MAX);
assert_eq!(result, Err(Error::Custom("value out of range")));
}
#[test]
fn test_try_from_u64_within_range() {
let valid_value: U64 = U64::from(AlloyOpTxType::Legacy as u64);
let op_tx = OpTxType::try_from(valid_value).unwrap();
assert_eq!(op_tx, OpTxType(AlloyOpTxType::Legacy));
}
#[test]
fn test_default() {
let default_tx = OpTxType::default();
assert_eq!(default_tx, OpTxType(AlloyOpTxType::Legacy));
}
#[test]
fn test_partial_eq_u8() {
let op_tx = OpTxType(AlloyOpTxType::Legacy);
assert_eq!(op_tx, AlloyOpTxType::Legacy as u8);
}
#[test]
fn test_encodable() {
let op_tx = OpTxType(AlloyOpTxType::Legacy);
let mut buf = BytesMut::new();
op_tx.encode(&mut buf);
assert_eq!(buf, BytesMut::from(&[0x80][..]));
}
#[test]
fn test_decodable_success() {
// Using the RLP-encoded form of 0, which is `b"\x80"`
let mut buf: &[u8] = &[0x80];
let decoded_tx = OpTxType::decode(&mut buf).unwrap();
assert_eq!(decoded_tx, OpTxType(AlloyOpTxType::Legacy));
}
#[test]
fn test_decodable_invalid() {
let mut buf: &[u8] = &[255];
let result = OpTxType::decode(&mut buf);
assert!(result.is_err());
}
#[rstest] #[rstest]
#[case(OpTxType(AlloyOpTxType::Legacy), COMPACT_IDENTIFIER_LEGACY, vec![])] #[case(OpTxType::Legacy, COMPACT_IDENTIFIER_LEGACY, vec![])]
#[case(OpTxType(AlloyOpTxType::Eip2930), COMPACT_IDENTIFIER_EIP2930, vec![])] #[case(OpTxType::Eip2930, COMPACT_IDENTIFIER_EIP2930, vec![])]
#[case(OpTxType(AlloyOpTxType::Eip1559), COMPACT_IDENTIFIER_EIP1559, vec![])] #[case(OpTxType::Eip1559, COMPACT_IDENTIFIER_EIP1559, vec![])]
#[case(OpTxType(AlloyOpTxType::Eip7702), COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID])] #[case(OpTxType::Eip7702, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID])]
#[case(OpTxType(AlloyOpTxType::Deposit), COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![DEPOSIT_TX_TYPE_ID])] #[case(OpTxType::Deposit, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![DEPOSIT_TX_TYPE_ID])]
fn test_txtype_to_compact( fn test_txtype_to_compact(
#[case] tx_type: OpTxType, #[case] tx_type: OpTxType,
#[case] expected_identifier: usize, #[case] expected_identifier: usize,
@ -297,11 +32,11 @@ mod tests {
} }
#[rstest] #[rstest]
#[case(OpTxType(AlloyOpTxType::Legacy), COMPACT_IDENTIFIER_LEGACY, vec![])] #[case(OpTxType::Legacy, COMPACT_IDENTIFIER_LEGACY, vec![])]
#[case(OpTxType(AlloyOpTxType::Eip2930), COMPACT_IDENTIFIER_EIP2930, vec![])] #[case(OpTxType::Eip2930, COMPACT_IDENTIFIER_EIP2930, vec![])]
#[case(OpTxType(AlloyOpTxType::Eip1559), COMPACT_IDENTIFIER_EIP1559, vec![])] #[case(OpTxType::Eip1559, COMPACT_IDENTIFIER_EIP1559, vec![])]
#[case(OpTxType(AlloyOpTxType::Eip7702), COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID])] #[case(OpTxType::Eip7702, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID])]
#[case(OpTxType(AlloyOpTxType::Deposit), COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![DEPOSIT_TX_TYPE_ID])] #[case(OpTxType::Deposit, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![DEPOSIT_TX_TYPE_ID])]
fn test_txtype_from_compact( fn test_txtype_from_compact(
#[case] expected_type: OpTxType, #[case] expected_type: OpTxType,
#[case] identifier: usize, #[case] identifier: usize,

View File

@ -23,6 +23,9 @@ alloy-primitives.workspace = true
alloy-rlp.workspace = true alloy-rlp.workspace = true
revm-primitives.workspace = true revm-primitives.workspace = true
# op
op-alloy-consensus = { workspace = true, optional = true }
# misc # misc
byteorder = { workspace = true, optional = true } byteorder = { workspace = true, optional = true }
bytes.workspace = true bytes.workspace = true
@ -78,28 +81,34 @@ arbitrary = [
"dep:proptest-arbitrary-interop", "dep:proptest-arbitrary-interop",
"alloy-eips/arbitrary", "alloy-eips/arbitrary",
"revm-primitives/arbitrary", "revm-primitives/arbitrary",
"reth-codecs?/arbitrary" "reth-codecs?/arbitrary",
"op-alloy-consensus?/arbitrary"
] ]
serde-bincode-compat = [ serde-bincode-compat = [
"serde", "serde",
"serde_with", "serde_with",
"alloy-consensus/serde-bincode-compat", "alloy-consensus/serde-bincode-compat",
"alloy-eips/serde-bincode-compat" "alloy-eips/serde-bincode-compat",
"op-alloy-consensus?/serde-bincode-compat"
] ]
serde = [ serde = [
"dep:serde", "dep:serde",
"alloy-consensus/serde", "alloy-consensus/serde",
"alloy-eips/serde", "alloy-eips/serde",
"alloy-primitives/serde", "alloy-primitives/serde",
"bytes/serde", "bytes/serde",
"rand/serde", "rand/serde",
"reth-codecs?/serde", "reth-codecs?/serde",
"revm-primitives/serde",
"roaring/serde",
"revm-primitives/serde", "revm-primitives/serde",
"roaring/serde",
"revm-primitives/serde",
"op-alloy-consensus?/serde"
] ]
reth-codec = [ reth-codec = [
"dep:reth-codecs", "dep:reth-codecs",
"dep:modular-bitfield", "dep:modular-bitfield",
"dep:byteorder", "dep:byteorder",
] ]
op = [
"dep:op-alloy-consensus",
]

View File

@ -46,6 +46,13 @@ macro_rules! impl_in_mem_size {
impl_in_mem_size!(Header, TxLegacy, TxEip2930, TxEip1559, TxEip7702, TxEip4844); impl_in_mem_size!(Header, TxLegacy, TxEip2930, TxEip1559, TxEip7702, TxEip4844);
#[cfg(feature = "op")]
impl InMemorySize for op_alloy_consensus::OpTxType {
fn size(&self) -> usize {
1
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -1,10 +1,8 @@
//! Abstraction of transaction envelope type ID. //! Abstraction of transaction envelope type ID.
use core::fmt;
use alloy_primitives::{U64, U8};
use crate::{InMemorySize, MaybeArbitrary, MaybeCompact}; use crate::{InMemorySize, MaybeArbitrary, MaybeCompact};
use alloy_primitives::{U64, U8};
use core::fmt;
/// Helper trait that unifies all behaviour required by transaction type ID to support full node /// Helper trait that unifies all behaviour required by transaction type ID to support full node
/// operations. /// operations.
@ -60,3 +58,26 @@ pub trait TxType:
!self.is_eip4844() !self.is_eip4844()
} }
} }
#[cfg(feature = "op")]
impl TxType for op_alloy_consensus::OpTxType {
fn is_legacy(&self) -> bool {
matches!(self, Self::Legacy)
}
fn is_eip2930(&self) -> bool {
matches!(self, Self::Eip2930)
}
fn is_eip1559(&self) -> bool {
matches!(self, Self::Eip1559)
}
fn is_eip4844(&self) -> bool {
false
}
fn is_eip7702(&self) -> bool {
matches!(self, Self::Eip7702)
}
}

View File

@ -1,9 +1,11 @@
//! Compact implementation for [`AlloyTxDeposit`] //! Compact implementation for [`AlloyTxDeposit`]
use alloy_consensus::constants::EIP7702_TX_TYPE_ID;
use crate::Compact; use crate::Compact;
use alloy_primitives::{Address, Bytes, TxKind, B256, U256}; use alloy_primitives::{Address, Bytes, TxKind, B256, U256};
use op_alloy_consensus::TxDeposit as AlloyTxDeposit; use op_alloy_consensus::{OpTxType, TxDeposit as AlloyTxDeposit};
use reth_codecs_derive::add_arbitrary_tests; use reth_codecs_derive::add_arbitrary_tests;
use crate::txtype::{COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930, COMPACT_IDENTIFIER_LEGACY};
/// Deposit transactions, also known as deposits are initiated on L1, and executed on L2. /// Deposit transactions, also known as deposits are initiated on L1, and executed on L2.
/// ///
@ -65,3 +67,51 @@ impl Compact for AlloyTxDeposit {
(alloy_tx, buf) (alloy_tx, buf)
} }
} }
impl crate::Compact for OpTxType {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
use crate::txtype::*;
match self {
Self::Legacy => COMPACT_IDENTIFIER_LEGACY,
Self::Eip2930 => COMPACT_IDENTIFIER_EIP2930,
Self::Eip1559 => COMPACT_IDENTIFIER_EIP1559,
Self::Eip7702 => {
buf.put_u8(EIP7702_TX_TYPE_ID);
COMPACT_EXTENDED_IDENTIFIER_FLAG
}
Self::Deposit => {
buf.put_u8(op_alloy_consensus::DEPOSIT_TX_TYPE_ID);
COMPACT_EXTENDED_IDENTIFIER_FLAG
}
}
}
// For backwards compatibility purposes only 2 bits of the type are encoded in the identifier
// parameter. In the case of a [`COMPACT_EXTENDED_IDENTIFIER_FLAG`], the full transaction type
// is read from the buffer as a single byte.
fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
use bytes::Buf;
(
match identifier {
COMPACT_IDENTIFIER_LEGACY => Self::Legacy,
COMPACT_IDENTIFIER_EIP2930 => Self::Eip2930,
COMPACT_IDENTIFIER_EIP1559 => Self::Eip1559,
COMPACT_EXTENDED_IDENTIFIER_FLAG => {
let extended_identifier = buf.get_u8();
match extended_identifier {
EIP7702_TX_TYPE_ID => Self::Eip7702,
op_alloy_consensus::DEPOSIT_TX_TYPE_ID => Self::Deposit,
_ => panic!("Unsupported TxType identifier: {extended_identifier}"),
}
}
_ => panic!("Unknown identifier for TxType: {identifier}"),
},
buf,
)
}
}