mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-26 07:38:59 -05:00
feat(storage): Implement Compact for OpTxEnvelope from op_alloy using blanket impl (#15230)
This commit is contained in:
@@ -778,3 +778,37 @@ pub mod serde_bincode_compat {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use proptest::proptest;
|
||||
use proptest_arbitrary_interop::arb;
|
||||
use reth_codecs::Compact;
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn test_roundtrip_compact_encode_envelope(reth_tx in arb::<OpTransactionSigned>()) {
|
||||
let mut expected_buf = Vec::<u8>::new();
|
||||
let expected_len = reth_tx.to_compact(&mut expected_buf);
|
||||
|
||||
let mut actual_but = Vec::<u8>::new();
|
||||
let alloy_tx = OpTxEnvelope::from(reth_tx);
|
||||
let actual_len = alloy_tx.to_compact(&mut actual_but);
|
||||
|
||||
assert_eq!(actual_but, expected_buf);
|
||||
assert_eq!(actual_len, expected_len);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_roundtrip_compact_decode_envelope(reth_tx in arb::<OpTransactionSigned>()) {
|
||||
let mut buf = Vec::<u8>::new();
|
||||
let len = reth_tx.to_compact(&mut buf);
|
||||
|
||||
let (actual_tx, _) = OpTxEnvelope::from_compact(&buf, len);
|
||||
let expected_tx = OpTxEnvelope::from(reth_tx);
|
||||
|
||||
assert_eq!(actual_tx, expected_tx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use bytes::{Buf, BufMut};
|
||||
/// serialized separately.
|
||||
///
|
||||
/// See [`ToTxCompact::to_tx_compact`].
|
||||
trait ToTxCompact {
|
||||
pub(super) trait ToTxCompact {
|
||||
/// Serializes inner transaction using [`Compact`] encoding. Writes the result into `buf`.
|
||||
///
|
||||
/// The written bytes do not contain signature and transaction type. This information be needs
|
||||
@@ -30,14 +30,20 @@ trait ToTxCompact {
|
||||
/// separately.
|
||||
///
|
||||
/// See [`FromTxCompact::from_tx_compact`].
|
||||
trait FromTxCompact {
|
||||
pub(super) trait FromTxCompact {
|
||||
type TxType;
|
||||
|
||||
/// Deserializes inner transaction using [`Compact`] encoding. The concrete type is determined
|
||||
/// by `tx_type`. The `signature` is added to create typed and signed transaction.
|
||||
///
|
||||
/// Returns a tuple of 2 elements. The first element is the deserialized value and the second
|
||||
/// is a byte slice created from `buf` with a starting position advanced by the exact amount
|
||||
/// of bytes consumed for this process.
|
||||
fn from_tx_compact(buf: &[u8], tx_type: TxType, signature: PrimitiveSignature) -> (Self, &[u8])
|
||||
fn from_tx_compact(
|
||||
buf: &[u8],
|
||||
tx_type: Self::TxType,
|
||||
signature: PrimitiveSignature,
|
||||
) -> (Self, &[u8])
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
@@ -55,6 +61,8 @@ impl<Eip4844: Compact + Transaction> ToTxCompact for EthereumTxEnvelope<Eip4844>
|
||||
}
|
||||
|
||||
impl<Eip4844: Compact + Transaction> FromTxCompact for EthereumTxEnvelope<Eip4844> {
|
||||
type TxType = TxType;
|
||||
|
||||
fn from_tx_compact(
|
||||
buf: &[u8],
|
||||
tx_type: TxType,
|
||||
@@ -90,9 +98,39 @@ impl<Eip4844: Compact + Transaction> FromTxCompact for EthereumTxEnvelope<Eip484
|
||||
}
|
||||
}
|
||||
|
||||
impl<Eip4844: Compact + RlpEcdsaEncodableTx + Transaction + Send + Sync> Compact
|
||||
pub(super) trait Envelope: FromTxCompact<TxType: Compact> {
|
||||
fn signature(&self) -> &PrimitiveSignature;
|
||||
fn tx_type(&self) -> Self::TxType;
|
||||
}
|
||||
|
||||
impl<Eip4844: Compact + Transaction + RlpEcdsaEncodableTx> Envelope
|
||||
for EthereumTxEnvelope<Eip4844>
|
||||
{
|
||||
fn signature(&self) -> &PrimitiveSignature {
|
||||
Self::signature(self)
|
||||
}
|
||||
|
||||
fn tx_type(&self) -> Self::TxType {
|
||||
Self::tx_type(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) trait CompactEnvelope: Sized {
|
||||
/// Takes a buffer which can be written to. *Ideally*, it returns the length written to.
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
B: BufMut + AsMut<[u8]>;
|
||||
|
||||
/// Takes a buffer which can be read from. Returns the object and `buf` with its internal cursor
|
||||
/// advanced (eg.`.advance(len)`).
|
||||
///
|
||||
/// `len` can either be the `buf` remaining length, or the length of the compacted type.
|
||||
///
|
||||
/// It will panic, if `len` is smaller than `buf.len()`.
|
||||
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]);
|
||||
}
|
||||
|
||||
impl<T: Envelope + ToTxCompact + Transaction + Send + Sync> CompactEnvelope for T {
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
B: BufMut + AsMut<[u8]>,
|
||||
@@ -147,7 +185,7 @@ impl<Eip4844: Compact + RlpEcdsaEncodableTx + Transaction + Send + Sync> Compact
|
||||
let zstd_bit = flags >> 3;
|
||||
|
||||
let (signature, buf) = PrimitiveSignature::from_compact(buf, sig_bit);
|
||||
let (tx_type, buf) = TxType::from_compact(buf, tx_bits);
|
||||
let (tx_type, buf) = T::TxType::from_compact(buf, tx_bits);
|
||||
|
||||
let (transaction, buf) = if zstd_bit != 0 {
|
||||
#[cfg(feature = "std")]
|
||||
@@ -177,3 +215,18 @@ impl<Eip4844: Compact + RlpEcdsaEncodableTx + Transaction + Send + Sync> Compact
|
||||
(transaction, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Eip4844: Compact + RlpEcdsaEncodableTx + Transaction + Send + Sync> Compact
|
||||
for EthereumTxEnvelope<Eip4844>
|
||||
{
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
B: BufMut + AsMut<[u8]>,
|
||||
{
|
||||
<Self as CompactEnvelope>::to_compact(self, buf)
|
||||
}
|
||||
|
||||
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
|
||||
<Self as CompactEnvelope>::from_compact(buf, len)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
//! Compact implementation for [`AlloyTxDeposit`]
|
||||
|
||||
use alloy_consensus::constants::EIP7702_TX_TYPE_ID;
|
||||
use crate::Compact;
|
||||
use alloy_primitives::{Address, Bytes, TxKind, B256, U256};
|
||||
use op_alloy_consensus::{OpTxType, OpTypedTransaction, TxDeposit as AlloyTxDeposit};
|
||||
use crate::{
|
||||
alloy::transaction::ethereum::{CompactEnvelope, Envelope, FromTxCompact, ToTxCompact},
|
||||
generate_tests,
|
||||
txtype::{
|
||||
COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930,
|
||||
COMPACT_IDENTIFIER_LEGACY,
|
||||
},
|
||||
Compact,
|
||||
};
|
||||
use alloy_consensus::{
|
||||
constants::EIP7702_TX_TYPE_ID, Signed, TxEip1559, TxEip2930, TxEip7702, TxLegacy,
|
||||
};
|
||||
use alloy_primitives::{Address, Bytes, PrimitiveSignature, Sealed, TxKind, B256, U256};
|
||||
use bytes::BufMut;
|
||||
use op_alloy_consensus::{OpTxEnvelope, OpTxType, OpTypedTransaction, TxDeposit as AlloyTxDeposit};
|
||||
use reth_codecs_derive::add_arbitrary_tests;
|
||||
use crate::txtype::{COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930, COMPACT_IDENTIFIER_LEGACY};
|
||||
use crate::generate_tests;
|
||||
|
||||
/// Deposit transactions, also known as deposits are initiated on L1, and executed on L2.
|
||||
///
|
||||
@@ -69,7 +78,6 @@ impl Compact for AlloyTxDeposit {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl crate::Compact for OpTxType {
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
@@ -160,4 +168,86 @@ impl Compact for OpTypedTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTxCompact for OpTxEnvelope {
|
||||
fn to_tx_compact(&self, buf: &mut (impl BufMut + AsMut<[u8]>)) {
|
||||
match self {
|
||||
Self::Legacy(tx) => tx.tx().to_compact(buf),
|
||||
Self::Eip2930(tx) => tx.tx().to_compact(buf),
|
||||
Self::Eip1559(tx) => tx.tx().to_compact(buf),
|
||||
Self::Eip7702(tx) => tx.tx().to_compact(buf),
|
||||
Self::Deposit(tx) => tx.to_compact(buf),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl FromTxCompact for OpTxEnvelope {
|
||||
type TxType = OpTxType;
|
||||
|
||||
fn from_tx_compact(
|
||||
buf: &[u8],
|
||||
tx_type: OpTxType,
|
||||
signature: PrimitiveSignature,
|
||||
) -> (Self, &[u8]) {
|
||||
match tx_type {
|
||||
OpTxType::Legacy => {
|
||||
let (tx, buf) = TxLegacy::from_compact(buf, buf.len());
|
||||
let tx = Signed::new_unhashed(tx, signature);
|
||||
(Self::Legacy(tx), buf)
|
||||
}
|
||||
OpTxType::Eip2930 => {
|
||||
let (tx, buf) = TxEip2930::from_compact(buf, buf.len());
|
||||
let tx = Signed::new_unhashed(tx, signature);
|
||||
(Self::Eip2930(tx), buf)
|
||||
}
|
||||
OpTxType::Eip1559 => {
|
||||
let (tx, buf) = TxEip1559::from_compact(buf, buf.len());
|
||||
let tx = Signed::new_unhashed(tx, signature);
|
||||
(Self::Eip1559(tx), buf)
|
||||
}
|
||||
OpTxType::Eip7702 => {
|
||||
let (tx, buf) = TxEip7702::from_compact(buf, buf.len());
|
||||
let tx = Signed::new_unhashed(tx, signature);
|
||||
(Self::Eip7702(tx), buf)
|
||||
}
|
||||
OpTxType::Deposit => {
|
||||
let (tx, buf) = op_alloy_consensus::TxDeposit::from_compact(buf, buf.len());
|
||||
let tx = Sealed::new(tx);
|
||||
(Self::Deposit(tx), buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DEPOSIT_SIGNATURE: PrimitiveSignature =
|
||||
PrimitiveSignature::new(U256::ZERO, U256::ZERO, false);
|
||||
|
||||
impl Envelope for OpTxEnvelope {
|
||||
fn signature(&self) -> &PrimitiveSignature {
|
||||
match self {
|
||||
Self::Legacy(tx) => tx.signature(),
|
||||
Self::Eip2930(tx) => tx.signature(),
|
||||
Self::Eip1559(tx) => tx.signature(),
|
||||
Self::Eip7702(tx) => tx.signature(),
|
||||
Self::Deposit(_) => &DEPOSIT_SIGNATURE,
|
||||
}
|
||||
}
|
||||
|
||||
fn tx_type(&self) -> Self::TxType {
|
||||
Self::tx_type(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Compact for OpTxEnvelope {
|
||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||
where
|
||||
B: BufMut + AsMut<[u8]>,
|
||||
{
|
||||
CompactEnvelope::to_compact(self, buf)
|
||||
}
|
||||
|
||||
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
|
||||
CompactEnvelope::from_compact(buf, len)
|
||||
}
|
||||
}
|
||||
|
||||
generate_tests!(#[crate, compact] OpTypedTransaction, OpTypedTransactionTests);
|
||||
|
||||
Reference in New Issue
Block a user