mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore: use OpTypedTransaction directly (#13350)
This commit is contained in:
@ -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;
|
||||
|
||||
@ -1,201 +1,4 @@
|
||||
//! Wrapper of [`OpTypedTransaction`], that implements reth database encoding [`Compact`].
|
||||
//! Optimism transaction types
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
@ -47,7 +47,7 @@ pub struct OpTransactionSigned {
|
||||
/// Raw transaction info
|
||||
#[deref]
|
||||
#[as_ref]
|
||||
pub transaction: OpTransaction,
|
||||
pub transaction: OpTypedTransaction,
|
||||
}
|
||||
|
||||
impl OpTransactionSigned {
|
||||
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -93,8 +93,8 @@ impl SignedTransaction for OpTransactionSigned {
|
||||
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)
|
||||
if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = &self.transaction {
|
||||
return Some(*from)
|
||||
}
|
||||
|
||||
let Self { transaction, signature, .. } = self;
|
||||
@ -103,14 +103,16 @@ impl SignedTransaction for OpTransactionSigned {
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -123,7 +125,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);
|
||||
@ -252,7 +254,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)
|
||||
}
|
||||
@ -272,7 +274,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)
|
||||
@ -408,16 +410,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 &&
|
||||
@ -463,7 +455,7 @@ impl<'a> arbitrary::Arbitrary<'a> for OpTransactionSigned {
|
||||
}
|
||||
|
||||
/// Calculates the signing hash for the transaction.
|
||||
pub fn signature_hash(tx: &OpTypedTransaction) -> B256 {
|
||||
fn signature_hash(tx: &OpTypedTransaction) -> B256 {
|
||||
match tx {
|
||||
OpTypedTransaction::Legacy(tx) => tx.signature_hash(),
|
||||
OpTypedTransaction::Eip2930(tx) => tx.signature_hash(),
|
||||
|
||||
@ -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::*;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
use alloy_consensus::constants::EIP7702_TX_TYPE_ID;
|
||||
use crate::Compact;
|
||||
use alloy_primitives::{Address, Bytes, TxKind, B256, U256};
|
||||
use op_alloy_consensus::{OpTxType, TxDeposit as AlloyTxDeposit};
|
||||
use op_alloy_consensus::{OpTxType, OpTypedTransaction, TxDeposit as AlloyTxDeposit, DEPOSIT_TX_TYPE_ID};
|
||||
use reth_codecs_derive::add_arbitrary_tests;
|
||||
use crate::txtype::{COMPACT_EXTENDED_IDENTIFIER_FLAG, COMPACT_IDENTIFIER_EIP1559, COMPACT_IDENTIFIER_EIP2930, COMPACT_IDENTIFIER_LEGACY};
|
||||
|
||||
@ -115,3 +115,59 @@ impl crate::Compact for OpTxType {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Compact for OpTypedTransaction {
|
||||
fn to_compact<B>(&self, out: &mut B) -> usize
|
||||
where
|
||||
B: bytes::BufMut + AsMut<[u8]>,
|
||||
{
|
||||
match self {
|
||||
Self::Legacy(tx) => tx.to_compact(out),
|
||||
Self::Eip2930(tx) => tx.to_compact(out),
|
||||
Self::Eip1559(tx) => tx.to_compact(out),
|
||||
Self::Eip7702(tx) => tx.to_compact(out),
|
||||
Self::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) = Compact::from_compact(buf, buf.len());
|
||||
(Self::Legacy(tx), buf)
|
||||
}
|
||||
COMPACT_IDENTIFIER_EIP2930 => {
|
||||
let (tx, buf) = Compact::from_compact(buf, buf.len());
|
||||
(Self::Eip2930(tx), buf)
|
||||
}
|
||||
COMPACT_IDENTIFIER_EIP1559 => {
|
||||
let (tx, buf) = Compact::from_compact(buf, buf.len());
|
||||
(Self::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) = Compact::from_compact(buf, buf.len());
|
||||
(Self::Eip7702(tx), buf)
|
||||
}
|
||||
DEPOSIT_TX_TYPE_ID => {
|
||||
let (tx, buf) = Compact::from_compact(buf, buf.len());
|
||||
(Self::Deposit(tx), buf)
|
||||
}
|
||||
_ => unreachable!(
|
||||
"Junk data in database: unknown Transaction variant: {identifier}"
|
||||
),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("Junk data in database: unknown Transaction variant: {identifier}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user