reth_codecs/alloy/transaction/
txtype.rs

1//! Compact implementation for [`TxType`]
2
3use crate::txtype::{
4    COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930,
5    COMPACT_IDENTIFIER_LEGACY,
6};
7use alloy_consensus::{
8    constants::{EIP4844_TX_TYPE_ID, EIP7702_TX_TYPE_ID, SEISMIC_TX_TYPE_ID},
9    TxType,
10};
11
12impl crate::Compact for TxType {
13    fn to_compact<B>(&self, buf: &mut B) -> usize
14    where
15        B: bytes::BufMut + AsMut<[u8]>,
16    {
17        use crate::txtype::*;
18
19        match self {
20            Self::Legacy => COMPACT_IDENTIFIER_LEGACY,
21            Self::Eip2930 => COMPACT_IDENTIFIER_EIP2930,
22            Self::Eip1559 => COMPACT_IDENTIFIER_EIP1559,
23            Self::Eip4844 => {
24                buf.put_u8(EIP4844_TX_TYPE_ID);
25                COMPACT_EXTENDED_IDENTIFIER_FLAG
26            }
27            Self::Eip7702 => {
28                buf.put_u8(EIP7702_TX_TYPE_ID);
29                COMPACT_EXTENDED_IDENTIFIER_FLAG
30            }
31            Self::Seismic => {
32                buf.put_u8(SEISMIC_TX_TYPE_ID);
33                COMPACT_EXTENDED_IDENTIFIER_FLAG
34            }
35        }
36    }
37
38    // For backwards compatibility purposes only 2 bits of the type are encoded in the identifier
39    // parameter. In the case of a [`COMPACT_EXTENDED_IDENTIFIER_FLAG`], the full transaction type
40    // is read from the buffer as a single byte.
41    fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
42        use bytes::Buf;
43        (
44            match identifier {
45                COMPACT_IDENTIFIER_LEGACY => Self::Legacy,
46                COMPACT_IDENTIFIER_EIP2930 => Self::Eip2930,
47                COMPACT_IDENTIFIER_EIP1559 => Self::Eip1559,
48                COMPACT_EXTENDED_IDENTIFIER_FLAG => {
49                    let extended_identifier = buf.get_u8();
50                    match extended_identifier {
51                        EIP4844_TX_TYPE_ID => Self::Eip4844,
52                        EIP7702_TX_TYPE_ID => Self::Eip7702,
53                        SEISMIC_TX_TYPE_ID => Self::Seismic,
54                        _ => panic!("Unsupported TxType identifier: {extended_identifier}"),
55                    }
56                }
57                _ => panic!("Unknown identifier for TxType: {identifier}"),
58            },
59            buf,
60        )
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use rstest::rstest;
68
69    use crate::Compact;
70    use alloy_consensus::constants::{EIP4844_TX_TYPE_ID, EIP7702_TX_TYPE_ID};
71
72    #[rstest]
73    #[case(TxType::Legacy, COMPACT_IDENTIFIER_LEGACY, vec![])]
74    #[case(TxType::Eip2930, COMPACT_IDENTIFIER_EIP2930, vec![])]
75    #[case(TxType::Eip1559, COMPACT_IDENTIFIER_EIP1559, vec![])]
76    #[case(TxType::Eip4844, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP4844_TX_TYPE_ID])]
77    #[case(TxType::Eip7702, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID])]
78    fn test_txtype_to_compact(
79        #[case] tx_type: TxType,
80        #[case] expected_identifier: usize,
81        #[case] expected_buf: Vec<u8>,
82    ) {
83        let mut buf = vec![];
84        let identifier = tx_type.to_compact(&mut buf);
85
86        assert_eq!(identifier, expected_identifier, "Unexpected identifier for TxType {tx_type:?}",);
87        assert_eq!(buf, expected_buf, "Unexpected buffer for TxType {tx_type:?}",);
88    }
89
90    #[rstest]
91    #[case(TxType::Legacy, COMPACT_IDENTIFIER_LEGACY, vec![])]
92    #[case(TxType::Eip2930, COMPACT_IDENTIFIER_EIP2930, vec![])]
93    #[case(TxType::Eip1559, COMPACT_IDENTIFIER_EIP1559, vec![])]
94    #[case(TxType::Eip4844, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP4844_TX_TYPE_ID])]
95    #[case(TxType::Eip7702, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID])]
96    fn test_txtype_from_compact(
97        #[case] expected_type: TxType,
98        #[case] identifier: usize,
99        #[case] buf: Vec<u8>,
100    ) {
101        let (actual_type, remaining_buf) = TxType::from_compact(&buf, identifier);
102
103        assert_eq!(actual_type, expected_type, "Unexpected TxType for identifier {identifier}");
104        assert!(remaining_buf.is_empty(), "Buffer not fully consumed for identifier {identifier}");
105    }
106}