Skip to content

Commit

Permalink
chore: use OpTypedTransaction directly
Browse files Browse the repository at this point in the history
  • Loading branch information
klkvr committed Dec 12, 2024
1 parent cdb03ac commit c287b83
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 237 deletions.
2 changes: 1 addition & 1 deletion crates/optimism/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extern crate alloc;
pub mod bedrock;
pub mod transaction;

pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType, OpTransaction};
pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType};

mod receipt;
pub use receipt::OpReceipt;
Expand Down
197 changes: 0 additions & 197 deletions crates/optimism/primitives/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,200 +2,3 @@
pub mod signed;
pub mod tx_type;

use alloy_primitives::{bytes, Bytes, TxKind, Uint, B256};

#[cfg(any(test, feature = "reth-codec"))]
use alloy_consensus::constants::EIP7702_TX_TYPE_ID;
use alloy_consensus::{SignableTransaction, TxLegacy, Typed2718};
use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization};
use derive_more::{Constructor, Deref, From};
use op_alloy_consensus::OpTypedTransaction;
#[cfg(any(test, feature = "reth-codec"))]
use op_alloy_consensus::DEPOSIT_TX_TYPE_ID;
#[cfg(any(test, feature = "reth-codec"))]
use reth_codecs::Compact;
#[cfg(any(test, feature = "reth-codec"))]
use reth_primitives::transaction::{
COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930,
COMPACT_IDENTIFIER_LEGACY,
};
use reth_primitives_traits::InMemorySize;

#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Deref, Hash, From, Constructor)]
/// Optimistic transaction.
pub struct OpTransaction(OpTypedTransaction);

impl OpTransaction {
/// This encodes the transaction _without_ the signature, and is only suitable for creating a
/// hash intended for signing.
pub fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
match self.deref() {
OpTypedTransaction::Legacy(tx) => tx.encode_for_signing(out),
OpTypedTransaction::Eip2930(tx) => tx.encode_for_signing(out),
OpTypedTransaction::Eip1559(tx) => tx.encode_for_signing(out),
OpTypedTransaction::Eip7702(tx) => tx.encode_for_signing(out),
OpTypedTransaction::Deposit(_) => {}
}
}
}

impl Default for OpTransaction {
fn default() -> Self {
Self(OpTypedTransaction::Legacy(TxLegacy::default()))
}
}

#[cfg(any(test, feature = "reth-codec"))]
impl Compact for OpTransaction {
fn to_compact<B>(&self, out: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
match &self.0 {
OpTypedTransaction::Legacy(tx) => tx.to_compact(out),
OpTypedTransaction::Eip2930(tx) => tx.to_compact(out),
OpTypedTransaction::Eip1559(tx) => tx.to_compact(out),
OpTypedTransaction::Eip7702(tx) => tx.to_compact(out),
OpTypedTransaction::Deposit(tx) => tx.to_compact(out),
}
}

fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
use bytes::Buf;

match identifier {
COMPACT_IDENTIFIER_LEGACY => {
let (tx, buf) = TxLegacy::from_compact(buf, buf.len());
(Self(OpTypedTransaction::Legacy(tx)), buf)
}
COMPACT_IDENTIFIER_EIP2930 => {
let (tx, buf) =
alloy_consensus::transaction::TxEip2930::from_compact(buf, buf.len());
(Self(OpTypedTransaction::Eip2930(tx)), buf)
}
COMPACT_IDENTIFIER_EIP1559 => {
let (tx, buf) =
alloy_consensus::transaction::TxEip1559::from_compact(buf, buf.len());
(Self(OpTypedTransaction::Eip1559(tx)), buf)
}
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();
match identifier {
EIP7702_TX_TYPE_ID => {
let (tx, buf) =
alloy_consensus::transaction::TxEip7702::from_compact(buf, buf.len());
(Self(OpTypedTransaction::Eip7702(tx)), buf)
}
DEPOSIT_TX_TYPE_ID => {
let (tx, buf) = op_alloy_consensus::TxDeposit::from_compact(buf, buf.len());
(Self(OpTypedTransaction::Deposit(tx)), buf)
}
_ => unreachable!(
"Junk data in database: unknown Transaction variant: {identifier}"
),
}
}
_ => unreachable!("Junk data in database: unknown Transaction variant: {identifier}"),
}
}
}

impl alloy_consensus::Transaction for OpTransaction {
fn chain_id(&self) -> Option<u64> {
self.0.chain_id()
}

fn nonce(&self) -> u64 {
self.0.nonce()
}

fn gas_limit(&self) -> u64 {
self.0.gas_limit()
}

fn gas_price(&self) -> Option<u128> {
self.0.gas_price()
}

fn max_fee_per_gas(&self) -> u128 {
self.0.max_fee_per_gas()
}

fn max_priority_fee_per_gas(&self) -> Option<u128> {
self.0.max_priority_fee_per_gas()
}

fn max_fee_per_blob_gas(&self) -> Option<u128> {
self.0.max_fee_per_blob_gas()
}

fn priority_fee_or_price(&self) -> u128 {
self.0.priority_fee_or_price()
}

fn kind(&self) -> TxKind {
self.0.kind()
}

fn is_create(&self) -> bool {
self.0.is_create()
}

fn value(&self) -> Uint<256, 4> {
self.0.value()
}

fn input(&self) -> &Bytes {
self.0.input()
}

fn access_list(&self) -> Option<&AccessList> {
self.0.access_list()
}

fn blob_versioned_hashes(&self) -> Option<&[B256]> {
self.0.blob_versioned_hashes()
}

fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
self.0.authorization_list()
}

fn is_dynamic_fee(&self) -> bool {
self.0.is_dynamic_fee()
}

fn effective_gas_price(&self, base_fee: Option<u64>) -> u128 {
self.0.effective_gas_price(base_fee)
}

fn effective_tip_per_gas(&self, base_fee: u64) -> Option<u128> {
self.0.effective_tip_per_gas(base_fee)
}
}

impl InMemorySize for OpTransaction {
fn size(&self) -> usize {
match &self.0 {
OpTypedTransaction::Legacy(tx) => tx.size(),
OpTypedTransaction::Eip2930(tx) => tx.size(),
OpTypedTransaction::Eip1559(tx) => tx.size(),
OpTypedTransaction::Eip7702(tx) => tx.size(),
OpTypedTransaction::Deposit(tx) => tx.size(),
}
}
}

impl Typed2718 for OpTransaction {
fn ty(&self) -> u8 {
self.0.ty()
}
}
54 changes: 17 additions & 37 deletions crates/optimism/primitives/src/transaction/signed.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! A signed Optimism transaction.
use crate::{OpTransaction, OpTxType};
use crate::OpTxType;
use alloc::vec::Vec;
use alloy_consensus::{
transaction::RlpEcdsaTx, SignableTransaction, Transaction, TxEip1559, TxEip2930, TxEip7702,
Expand Down Expand Up @@ -47,7 +47,7 @@ pub struct OpTransactionSigned {
/// Raw transaction info
#[deref]
#[as_ref]
pub transaction: OpTransaction,
pub transaction: OpTypedTransaction,
}

impl OpTransactionSigned {
Expand All @@ -65,7 +65,7 @@ impl OpTransactionSigned {
///
/// Note: this only calculates the hash on the first [`TransactionSigned::hash`] call.
pub fn new_unhashed(transaction: OpTypedTransaction, signature: Signature) -> Self {
Self { hash: Default::default(), signature, transaction: OpTransaction::new(transaction) }
Self { hash: Default::default(), signature, transaction }
}
}

Expand All @@ -81,7 +81,7 @@ impl SignedTransaction for OpTransactionSigned {
fn recover_signer(&self) -> Option<Address> {
// Optimism's Deposit transaction does not have a signature. Directly return the
// `from` address.
if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = *self.transaction {
if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = self.transaction {
return Some(from)
}

Expand All @@ -90,27 +90,17 @@ impl SignedTransaction for OpTransactionSigned {
recover_signer(signature, signature_hash)
}

fn recover_signer_unchecked(&self) -> Option<Address> {
// Optimism's Deposit transaction does not have a signature. Directly return the
// `from` address.
if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = *self.transaction {
return Some(from)
}

let Self { transaction, signature, .. } = self;
let signature_hash = signature_hash(transaction);
recover_signer_unchecked(signature, signature_hash)
}

fn recover_signer_unchecked_with_buf(&self, buf: &mut Vec<u8>) -> Option<Address> {
// Optimism's Deposit transaction does not have a signature. Directly return the
// `from` address.
if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = *self.transaction {
return Some(from)
}
self.encode_for_signing(buf);
let signature_hash = keccak256(buf);
recover_signer_unchecked(&self.signature, signature_hash)
match &self.transaction {
// Optimism's Deposit transaction does not have a signature. Directly return the
// `from` address.
OpTypedTransaction::Deposit(tx) => return Some(tx.from),
OpTypedTransaction::Legacy(tx) => tx.encode_for_signing(buf),
OpTypedTransaction::Eip2930(tx) => tx.encode_for_signing(buf),
OpTypedTransaction::Eip1559(tx) => tx.encode_for_signing(buf),
OpTypedTransaction::Eip7702(tx) => tx.encode_for_signing(buf),
};
recover_signer_unchecked(&self.signature, keccak256(buf))
}

fn recalculate_hash(&self) -> B256 {
Expand All @@ -123,7 +113,7 @@ impl FillTxEnv for OpTransactionSigned {
let envelope = self.encoded_2718();

tx_env.caller = sender;
match self.transaction.deref() {
match &self.transaction {
OpTypedTransaction::Legacy(tx) => {
tx_env.gas_limit = tx.gas_limit;
tx_env.gas_price = U256::from(tx.gas_price);
Expand Down Expand Up @@ -252,7 +242,7 @@ impl Encodable2718 for OpTransactionSigned {
}

fn encode_2718_len(&self) -> usize {
match self.transaction.deref() {
match &self.transaction {
OpTypedTransaction::Legacy(legacy_tx) => {
legacy_tx.eip2718_encoded_length(&self.signature)
}
Expand All @@ -272,7 +262,7 @@ impl Encodable2718 for OpTransactionSigned {
fn encode_2718(&self, out: &mut dyn alloy_rlp::BufMut) {
let Self { transaction, signature, .. } = self;

match transaction.deref() {
match &transaction {
OpTypedTransaction::Legacy(legacy_tx) => {
// do nothing w/ with_header
legacy_tx.eip2718_encode(signature, out)
Expand Down Expand Up @@ -408,16 +398,6 @@ impl Typed2718 for OpTransactionSigned {
}
}

impl Default for OpTransactionSigned {
fn default() -> Self {
Self {
hash: Default::default(),
signature: Signature::test_signature(),
transaction: OpTransaction::new(OpTypedTransaction::Legacy(Default::default())),
}
}
}

impl PartialEq for OpTransactionSigned {
fn eq(&self, other: &Self) -> bool {
self.signature == other.signature &&
Expand Down
13 changes: 13 additions & 0 deletions crates/primitives-traits/src/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ impl InMemorySize for op_alloy_consensus::OpDepositReceipt {
}
}

#[cfg(feature = "op")]
impl InMemorySize for op_alloy_consensus::OpTypedTransaction {
fn size(&self) -> usize {
match self {
Self::Legacy(tx) => tx.size(),
Self::Eip2930(tx) => tx.size(),
Self::Eip1559(tx) => tx.size(),
Self::Eip7702(tx) => tx.size(),
Self::Deposit(tx) => tx.size(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
Loading

0 comments on commit c287b83

Please sign in to comment.