Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(reth-primitives): use COMPACT_EXTENDED_IDENTIFIER_FLAG #10926

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions crates/primitives/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ mod variant;
pub use op_alloy_consensus::TxDeposit;
#[cfg(feature = "optimism")]
pub use tx_type::DEPOSIT_TX_TYPE_ID;
#[cfg(any(test, feature = "reth-codec"))]
use tx_type::{
COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930,
COMPACT_IDENTIFIER_LEGACY,
};

#[cfg(test)]
use reth_codecs::Compact;
Expand Down Expand Up @@ -754,45 +759,45 @@ impl reth_codecs::Compact for Transaction {
}

// For backwards compatibility purposes, only 2 bits of the type are encoded in the identifier
// parameter. In the case of a 3, the full transaction type is read from the buffer as a
// single byte.
// parameter. In the case of a [`COMPACT_EXTENDED_IDENTIFIER_FLAG`], the full transaction type
// is read from the buffer as a single byte.
//
// # Panics
//
// A panic will be triggered if an identifier larger than 3 is passed from the database. For
// optimism a identifier with value 126 is allowed.
// optimism a identifier with value [`DEPOSIT_TX_TYPE_ID`] is allowed.
fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
match identifier {
0 => {
COMPACT_IDENTIFIER_LEGACY => {
let (tx, buf) = TxLegacy::from_compact(buf, buf.len());
(Self::Legacy(tx), buf)
}
1 => {
COMPACT_IDENTIFIER_EIP2930 => {
let (tx, buf) = TxEip2930::from_compact(buf, buf.len());
(Self::Eip2930(tx), buf)
}
2 => {
COMPACT_IDENTIFIER_EIP1559 => {
let (tx, buf) = TxEip1559::from_compact(buf, buf.len());
(Self::Eip1559(tx), buf)
}
3 => {
COMPACT_EXTENDED_IDENTIFIER_FLAG => {
// An identifier of 3 indicates that the transaction type did not fit into
// the backwards compatible 2 bit identifier, their transaction types are
// larger than 2 bits (eg. 4844 and Deposit Transactions). In this case,
// we need to read the concrete transaction type from the buffer by
// reading the full 8 bits (single byte) and match on this transaction type.
let identifier = buf.get_u8() as usize;
let identifier = buf.get_u8();
match identifier {
3 => {
EIP4844_TX_TYPE_ID => {
let (tx, buf) = TxEip4844::from_compact(buf, buf.len());
(Self::Eip4844(tx), buf)
}
4 => {
EIP7702_TX_TYPE_ID => {
let (tx, buf) = TxEip7702::from_compact(buf, buf.len());
(Self::Eip7702(tx), buf)
}
#[cfg(feature = "optimism")]
126 => {
DEPOSIT_TX_TYPE_ID => {
let (tx, buf) = TxDeposit::from_compact(buf, buf.len());
(Self::Deposit(tx), buf)
}
Expand Down
78 changes: 45 additions & 33 deletions crates/primitives/src/transaction/tx_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ use serde::{Deserialize, Serialize};
#[cfg(test)]
use reth_codecs::Compact;

/// Identifier parameter for legacy transaction
#[cfg(any(test, feature = "reth-codec"))]
pub(crate) const COMPACT_IDENTIFIER_LEGACY: usize = 0;

/// Identifier parameter for EIP-2930 transaction
#[cfg(any(test, feature = "reth-codec"))]
pub(crate) const COMPACT_IDENTIFIER_EIP2930: usize = 1;

/// Identifier parameter for EIP-1559 transaction
#[cfg(any(test, feature = "reth-codec"))]
pub(crate) const COMPACT_IDENTIFIER_EIP1559: usize = 2;

/// For backwards compatibility purposes only 2 bits of the type are encoded in the identifier
/// parameter. In the case of a 3, the full transaction type is read from the buffer as a
/// single byte.
/// parameter. In the case of a [`COMPACT_EXTENDED_IDENTIFIER_FLAG`], the full transaction type is
/// read from the buffer as a single byte.
#[cfg(any(test, feature = "reth-codec"))]
const COMPACT_EXTENDED_IDENTIFIER_FLAG: usize = 3;
pub(crate) const COMPACT_EXTENDED_IDENTIFIER_FLAG: usize = 3;

/// Identifier for legacy transaction, however [`TxLegacy`](crate::TxLegacy) this is technically not
/// typed.
Expand Down Expand Up @@ -144,35 +156,35 @@ impl reth_codecs::Compact for TxType {
B: bytes::BufMut + AsMut<[u8]>,
{
match self {
Self::Legacy => 0,
Self::Eip2930 => 1,
Self::Eip1559 => 2,
Self::Legacy => COMPACT_IDENTIFIER_LEGACY,
Self::Eip2930 => COMPACT_IDENTIFIER_EIP2930,
Self::Eip1559 => COMPACT_IDENTIFIER_EIP1559,
Self::Eip4844 => {
buf.put_u8(*self as u8);
buf.put_u8(EIP4844_TX_TYPE_ID);
COMPACT_EXTENDED_IDENTIFIER_FLAG
}
Self::Eip7702 => {
buf.put_u8(*self as u8);
buf.put_u8(EIP7702_TX_TYPE_ID);
COMPACT_EXTENDED_IDENTIFIER_FLAG
}
#[cfg(feature = "optimism")]
Self::Deposit => {
buf.put_u8(*self as u8);
buf.put_u8(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 3, the full transaction type is read from the buffer as a
// single byte.
// 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 {
0 => Self::Legacy,
1 => Self::Eip2930,
2 => Self::Eip1559,
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 {
Expand Down Expand Up @@ -243,34 +255,34 @@ mod tests {
#[test]
fn test_u64_to_tx_type() {
// Test for Legacy transaction
assert_eq!(TxType::try_from(U64::from(0)).unwrap(), TxType::Legacy);
assert_eq!(TxType::try_from(U64::from(LEGACY_TX_TYPE_ID)).unwrap(), TxType::Legacy);

// Test for EIP2930 transaction
assert_eq!(TxType::try_from(U64::from(1)).unwrap(), TxType::Eip2930);
assert_eq!(TxType::try_from(U64::from(EIP2930_TX_TYPE_ID)).unwrap(), TxType::Eip2930);

// Test for EIP1559 transaction
assert_eq!(TxType::try_from(U64::from(2)).unwrap(), TxType::Eip1559);
assert_eq!(TxType::try_from(U64::from(EIP1559_TX_TYPE_ID)).unwrap(), TxType::Eip1559);

// Test for EIP4844 transaction
assert_eq!(TxType::try_from(U64::from(3)).unwrap(), TxType::Eip4844);
assert_eq!(TxType::try_from(U64::from(EIP4844_TX_TYPE_ID)).unwrap(), TxType::Eip4844);

// Test for EIP7702 transaction
assert_eq!(TxType::try_from(U64::from(4)).unwrap(), TxType::Eip7702);
assert_eq!(TxType::try_from(U64::from(EIP7702_TX_TYPE_ID)).unwrap(), TxType::Eip7702);

// Test for Deposit transaction
#[cfg(feature = "optimism")]
assert_eq!(TxType::try_from(U64::from(126)).unwrap(), TxType::Deposit);
assert_eq!(TxType::try_from(U64::from(DEPOSIT_TX_TYPE_ID)).unwrap(), TxType::Deposit);

// For transactions with unsupported values
assert!(TxType::try_from(U64::from(5)).is_err());
assert!(TxType::try_from(U64::from(EIP7702_TX_TYPE_ID + 1)).is_err());
}

#[test]
fn test_txtype_to_compat() {
let cases = vec![
(TxType::Legacy, 0, vec![]),
(TxType::Eip2930, 1, vec![]),
(TxType::Eip1559, 2, vec![]),
(TxType::Legacy, COMPACT_IDENTIFIER_LEGACY, vec![]),
(TxType::Eip2930, COMPACT_IDENTIFIER_EIP2930, vec![]),
(TxType::Eip1559, COMPACT_IDENTIFIER_EIP1559, vec![]),
(TxType::Eip4844, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP4844_TX_TYPE_ID]),
(TxType::Eip7702, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID]),
#[cfg(feature = "optimism")]
Expand All @@ -291,9 +303,9 @@ mod tests {
#[test]
fn test_txtype_from_compact() {
let cases = vec![
(TxType::Legacy, 0, vec![]),
(TxType::Eip2930, 1, vec![]),
(TxType::Eip1559, 2, vec![]),
(TxType::Legacy, COMPACT_IDENTIFIER_LEGACY, vec![]),
(TxType::Eip2930, COMPACT_IDENTIFIER_EIP2930, vec![]),
(TxType::Eip1559, COMPACT_IDENTIFIER_EIP1559, vec![]),
(TxType::Eip4844, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP4844_TX_TYPE_ID]),
(TxType::Eip7702, COMPACT_EXTENDED_IDENTIFIER_FLAG, vec![EIP7702_TX_TYPE_ID]),
#[cfg(feature = "optimism")]
Expand All @@ -317,29 +329,29 @@ mod tests {
assert_eq!(tx_type, TxType::Legacy);

// Test for EIP2930 transaction
let tx_type = TxType::decode(&mut &[1u8][..]).unwrap();
let tx_type = TxType::decode(&mut &[EIP2930_TX_TYPE_ID][..]).unwrap();
assert_eq!(tx_type, TxType::Eip2930);

// Test for EIP1559 transaction
let tx_type = TxType::decode(&mut &[2u8][..]).unwrap();
let tx_type = TxType::decode(&mut &[EIP1559_TX_TYPE_ID][..]).unwrap();
assert_eq!(tx_type, TxType::Eip1559);

// Test for EIP4844 transaction
let tx_type = TxType::decode(&mut &[3u8][..]).unwrap();
let tx_type = TxType::decode(&mut &[EIP4844_TX_TYPE_ID][..]).unwrap();
assert_eq!(tx_type, TxType::Eip4844);

// Test for EIP7702 transaction
let tx_type = TxType::decode(&mut &[4u8][..]).unwrap();
let tx_type = TxType::decode(&mut &[EIP7702_TX_TYPE_ID][..]).unwrap();
assert_eq!(tx_type, TxType::Eip7702);

// Test random byte not in range
let buf = [rand::thread_rng().gen_range(5..=u8::MAX)];
let buf = [rand::thread_rng().gen_range(EIP7702_TX_TYPE_ID + 1..=u8::MAX)];
assert!(TxType::decode(&mut &buf[..]).is_err());

// Test for Deposit transaction
#[cfg(feature = "optimism")]
{
let buf = [126u8];
let buf = [DEPOSIT_TX_TYPE_ID];
let tx_type = TxType::decode(&mut &buf[..]).unwrap();
assert_eq!(tx_type, TxType::Deposit);
}
Expand Down
Loading