refactor(examples): Use TransactionEnvelope macro from alloy for CustomTransaction in the custom-node example (#17057)

This commit is contained in:
Roman Hodulák
2025-06-25 23:16:09 +02:00
committed by GitHub
parent 79d737e6c8
commit 7349abd126
6 changed files with 171 additions and 83 deletions

View File

@@ -257,28 +257,6 @@ impl TransactionEnv for CustomTxEnv {
}
}
impl FromRecoveredTx<CustomTransaction> for PaymentTxEnv {
fn from_recovered_tx(tx: &CustomTransaction, sender: Address) -> Self {
PaymentTxEnv(match tx {
CustomTransaction::BuiltIn(tx) => {
OpTransaction::<TxEnv>::from_recovered_tx(tx, sender).base
}
CustomTransaction::Other(tx) => TxEnv::from_recovered_tx(tx, sender),
})
}
}
impl FromTxWithEncoded<CustomTransaction> for PaymentTxEnv {
fn from_encoded_tx(tx: &CustomTransaction, sender: Address, encoded: Bytes) -> Self {
PaymentTxEnv(match tx {
CustomTransaction::BuiltIn(tx) => {
OpTransaction::<TxEnv>::from_encoded_tx(tx, sender, encoded).base
}
CustomTransaction::Other(tx) => TxEnv::from_encoded_tx(tx, sender, encoded),
})
}
}
impl FromRecoveredTx<TxPayment> for TxEnv {
fn from_recovered_tx(tx: &TxPayment, caller: Address) -> Self {
let TxPayment {
@@ -317,6 +295,12 @@ impl FromTxWithEncoded<CustomTransactionEnvelope> for TxEnv {
}
}
impl FromTxWithEncoded<TxPayment> for TxEnv {
fn from_encoded_tx(tx: &TxPayment, sender: Address, _encoded: Bytes) -> Self {
Self::from_recovered_tx(tx, sender)
}
}
impl FromRecoveredTx<OpTxEnvelope> for CustomTxEnv {
fn from_recovered_tx(tx: &OpTxEnvelope, sender: Address) -> Self {
Self::Op(OpTransaction::from_recovered_tx(tx, sender))
@@ -332,8 +316,8 @@ impl FromTxWithEncoded<OpTxEnvelope> for CustomTxEnv {
impl FromRecoveredTx<CustomTransaction> for CustomTxEnv {
fn from_recovered_tx(tx: &CustomTransaction, sender: Address) -> Self {
match tx {
CustomTransaction::BuiltIn(tx) => Self::from_recovered_tx(tx, sender),
CustomTransaction::Other(tx) => {
CustomTransaction::Op(tx) => Self::from_recovered_tx(tx, sender),
CustomTransaction::Payment(tx) => {
Self::Payment(PaymentTxEnv(TxEnv::from_recovered_tx(tx, sender)))
}
}
@@ -343,8 +327,8 @@ impl FromRecoveredTx<CustomTransaction> for CustomTxEnv {
impl FromTxWithEncoded<CustomTransaction> for CustomTxEnv {
fn from_encoded_tx(tx: &CustomTransaction, sender: Address, encoded: Bytes) -> Self {
match tx {
CustomTransaction::BuiltIn(tx) => Self::from_encoded_tx(tx, sender, encoded),
CustomTransaction::Other(tx) => {
CustomTransaction::Op(tx) => Self::from_encoded_tx(tx, sender, encoded),
CustomTransaction::Payment(tx) => {
Self::Payment(PaymentTxEnv(TxEnv::from_encoded_tx(tx, sender, encoded)))
}
}

View File

@@ -43,13 +43,11 @@ where
f: impl FnOnce(&ExecutionResult<<Self::Evm as Evm>::HaltReason>) -> CommitChanges,
) -> Result<Option<u64>, BlockExecutionError> {
match tx.tx() {
CustomTransaction::BuiltIn(op_tx) => {
self.inner.execute_transaction_with_commit_condition(
Recovered::new_unchecked(op_tx, *tx.signer()),
f,
)
}
CustomTransaction::Other(..) => todo!(),
CustomTransaction::Op(op_tx) => self.inner.execute_transaction_with_commit_condition(
Recovered::new_unchecked(op_tx, *tx.signer()),
f,
),
CustomTransaction::Payment(..) => todo!(),
}
}

View File

@@ -1,5 +1,28 @@
use crate::primitives::CustomTransactionEnvelope;
use crate::primitives::{CustomTransaction, CustomTransactionEnvelope};
use alloy_consensus::error::ValueError;
use op_alloy_consensus::OpPooledTransaction;
use reth_ethereum::primitives::Extended;
pub type CustomPooledTransaction = Extended<OpPooledTransaction, CustomTransactionEnvelope>;
impl From<CustomPooledTransaction> for CustomTransaction {
fn from(tx: CustomPooledTransaction) -> Self {
match tx {
CustomPooledTransaction::BuiltIn(tx) => Self::Op(tx.into()),
CustomPooledTransaction::Other(tx) => Self::Payment(tx),
}
}
}
impl TryFrom<CustomTransaction> for CustomPooledTransaction {
type Error = ValueError<CustomTransaction>;
fn try_from(tx: CustomTransaction) -> Result<Self, Self::Error> {
match tx {
CustomTransaction::Op(op) => Ok(Self::BuiltIn(
OpPooledTransaction::try_from(op).map_err(|op| op.map(CustomTransaction::Op))?,
)),
CustomTransaction::Payment(payment) => Ok(Self::Other(payment)),
}
}
}

View File

@@ -1,14 +1,17 @@
use super::{TxPayment, TxTypeCustom};
use super::TxPayment;
use alloy_consensus::{
crypto::{
secp256k1::{recover_signer, recover_signer_unchecked},
RecoveryError,
},
transaction::SignerRecoverable,
SignableTransaction, Signed, Transaction,
SignableTransaction, Signed, Transaction, TransactionEnvelope,
};
use alloy_eips::{eip2718::Eip2718Result, Decodable2718, Encodable2718, Typed2718};
use alloy_primitives::{keccak256, Sealed, Signature, TxHash};
use alloy_eips::{
eip2718::{Eip2718Result, IsTyped2718},
Decodable2718, Encodable2718, Typed2718,
};
use alloy_primitives::{bytes::Buf, keccak256, Sealed, Signature, TxHash, B256};
use alloy_rlp::{BufMut, Decodable, Encodable, Result as RlpResult};
use op_alloy_consensus::{OpTxEnvelope, TxDeposit};
use reth_codecs::{
@@ -16,19 +19,21 @@ use reth_codecs::{
Compact,
};
use reth_ethereum::primitives::{serde_bincode_compat::RlpBincode, InMemorySize};
use reth_op::{
primitives::{Extended, SignedTransaction},
OpTransaction,
};
use reth_op::{primitives::SignedTransaction, OpTransaction};
use revm_primitives::{Address, Bytes};
use serde::{Deserialize, Serialize};
/// An [`OpTxEnvelope`] that is [`Extended`] by one more variant of [`CustomTransactionEnvelope`].
pub type CustomTransaction = ExtendedOpTxEnvelope<CustomTransactionEnvelope>;
/// A [`SignedTransaction`] implementation that combines the [`OpTxEnvelope`] and another
/// transaction type.
pub type ExtendedOpTxEnvelope<T> = Extended<OpTxEnvelope, T>;
/// Either [`OpTxEnvelope`] or [`CustomTransactionEnvelope`].
#[derive(Debug, Clone, TransactionEnvelope)]
#[envelope(tx_type_name = TxTypeCustom)]
pub enum CustomTransaction {
/// A regular Optimism transaction as defined by [`OpTxEnvelope`].
#[envelope(flatten)]
Op(OpTxEnvelope),
/// A [`TxPayment`] tagged with type 0x7E.
#[envelope(ty = 42)]
Payment(CustomTransactionEnvelope),
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub struct CustomTransactionEnvelope {
@@ -98,7 +103,7 @@ impl Transaction for CustomTransactionEnvelope {
self.inner.tx().access_list()
}
fn blob_versioned_hashes(&self) -> Option<&[revm_primitives::B256]> {
fn blob_versioned_hashes(&self) -> Option<&[B256]> {
self.inner.tx().blob_versioned_hashes()
}
@@ -199,6 +204,7 @@ impl ToTxCompact for CustomTransactionEnvelope {
}
impl RlpBincode for CustomTransactionEnvelope {}
impl RlpBincode for CustomTransaction {}
impl reth_codecs::alloy::transaction::Envelope for CustomTransactionEnvelope {
fn signature(&self) -> &Signature {
@@ -206,14 +212,14 @@ impl reth_codecs::alloy::transaction::Envelope for CustomTransactionEnvelope {
}
fn tx_type(&self) -> Self::TxType {
TxTypeCustom::Custom
TxTypeCustom::Payment
}
}
impl Compact for CustomTransactionEnvelope {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: alloy_rlp::bytes::BufMut + AsMut<[u8]>,
B: BufMut + AsMut<[u8]>,
{
self.inner.tx().to_compact(buf)
}
@@ -226,6 +232,31 @@ impl Compact for CustomTransactionEnvelope {
}
}
impl reth_codecs::Compact for CustomTransaction {
fn to_compact<Buf>(&self, buf: &mut Buf) -> usize
where
Buf: BufMut + AsMut<[u8]>,
{
buf.put_u8(self.ty());
match self {
Self::Op(tx) => tx.to_compact(buf),
Self::Payment(tx) => tx.to_compact(buf),
}
}
fn from_compact(mut buf: &[u8], len: usize) -> (Self, &[u8]) {
let type_byte = buf.get_u8();
if <OpTxEnvelope as IsTyped2718>::is_type(type_byte) {
let (tx, remaining) = OpTxEnvelope::from_compact(buf, len);
return (Self::Op(tx), remaining);
}
let (tx, remaining) = CustomTransactionEnvelope::from_compact(buf, len);
(Self::Payment(tx), remaining)
}
}
impl OpTransaction for CustomTransactionEnvelope {
fn is_deposit(&self) -> bool {
false
@@ -235,3 +266,67 @@ impl OpTransaction for CustomTransactionEnvelope {
None
}
}
impl OpTransaction for CustomTransaction {
fn is_deposit(&self) -> bool {
match self {
CustomTransaction::Op(op) => op.is_deposit(),
CustomTransaction::Payment(payment) => payment.is_deposit(),
}
}
fn as_deposit(&self) -> Option<&Sealed<TxDeposit>> {
match self {
CustomTransaction::Op(op) => op.as_deposit(),
CustomTransaction::Payment(payment) => payment.as_deposit(),
}
}
}
impl SignerRecoverable for CustomTransaction {
fn recover_signer(&self) -> Result<Address, RecoveryError> {
match self {
CustomTransaction::Op(tx) => SignerRecoverable::recover_signer(tx),
CustomTransaction::Payment(tx) => SignerRecoverable::recover_signer(tx),
}
}
fn recover_signer_unchecked(&self) -> Result<Address, RecoveryError> {
match self {
CustomTransaction::Op(tx) => SignerRecoverable::recover_signer_unchecked(tx),
CustomTransaction::Payment(tx) => SignerRecoverable::recover_signer_unchecked(tx),
}
}
}
impl SignedTransaction for CustomTransaction {
fn recover_signer_unchecked_with_buf(
&self,
buf: &mut Vec<u8>,
) -> Result<Address, RecoveryError> {
match self {
CustomTransaction::Op(tx) => {
SignedTransaction::recover_signer_unchecked_with_buf(tx, buf)
}
CustomTransaction::Payment(tx) => {
SignedTransaction::recover_signer_unchecked_with_buf(tx, buf)
}
}
}
fn tx_hash(&self) -> &B256 {
match self {
CustomTransaction::Op(tx) => SignedTransaction::tx_hash(tx),
CustomTransaction::Payment(tx) => SignedTransaction::tx_hash(tx),
}
}
}
impl InMemorySize for CustomTransaction {
fn size(&self) -> usize {
match self {
CustomTransaction::Op(tx) => InMemorySize::size(tx),
CustomTransaction::Payment(tx) => InMemorySize::size(tx),
}
}
}

View File

@@ -1,4 +1,4 @@
use crate::primitives::{TxTypeCustom, TRANSFER_TX_TYPE_ID};
use crate::primitives::PAYMENT_TX_TYPE_ID;
use alloy_consensus::{
transaction::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx},
SignableTransaction, Transaction,
@@ -71,8 +71,8 @@ pub struct TxPayment {
impl TxPayment {
/// Get the transaction type
#[doc(alias = "transaction_type")]
pub const fn tx_type() -> TxTypeCustom {
TxTypeCustom::Custom
pub const fn tx_type() -> super::tx::TxTypeCustom {
super::tx::TxTypeCustom::Payment
}
/// Calculates a heuristic for the in-memory size of the [TxPayment]
@@ -115,7 +115,7 @@ impl RlpEcdsaEncodableTx for TxPayment {
}
impl RlpEcdsaDecodableTx for TxPayment {
const DEFAULT_TX_TYPE: u8 = { Self::tx_type() as u8 };
const DEFAULT_TX_TYPE: u8 = { PAYMENT_TX_TYPE_ID };
/// Decodes the inner [TxPayment] fields from RLP bytes.
///
@@ -244,7 +244,7 @@ impl Transaction for TxPayment {
impl Typed2718 for TxPayment {
fn ty(&self) -> u8 {
TRANSFER_TX_TYPE_ID
PAYMENT_TX_TYPE_ID
}
}
@@ -254,7 +254,7 @@ impl SignableTransaction<Signature> for TxPayment {
}
fn encode_for_signing(&self, out: &mut dyn alloy_rlp::BufMut) {
out.put_u8(Self::tx_type() as u8);
out.put_u8(Self::tx_type().ty());
self.encode(out)
}

View File

@@ -1,21 +1,8 @@
use crate::primitives::TxTypeCustom;
use alloy_primitives::bytes::{Buf, BufMut};
use reth_codecs::{txtype::COMPACT_EXTENDED_IDENTIFIER_FLAG, Compact};
use serde::{Deserialize, Serialize};
pub const TRANSFER_TX_TYPE_ID: u8 = 42;
/// An enum for the custom transaction type(s)
#[repr(u8)]
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub enum TxTypeCustom {
Custom = TRANSFER_TX_TYPE_ID,
}
impl From<TxTypeCustom> for u8 {
fn from(value: TxTypeCustom) -> Self {
value as Self
}
}
pub const PAYMENT_TX_TYPE_ID: u8 = 42;
impl Compact for TxTypeCustom {
fn to_compact<B>(&self, buf: &mut B) -> usize
@@ -23,26 +10,27 @@ impl Compact for TxTypeCustom {
B: BufMut + AsMut<[u8]>,
{
match self {
Self::Custom => {
buf.put_u8(TRANSFER_TX_TYPE_ID);
Self::Op(ty) => ty.to_compact(buf),
Self::Payment => {
buf.put_u8(PAYMENT_TX_TYPE_ID);
COMPACT_EXTENDED_IDENTIFIER_FLAG
}
}
}
fn from_compact(mut buf: &[u8], identifier: usize) -> (Self, &[u8]) {
(
match identifier {
COMPACT_EXTENDED_IDENTIFIER_FLAG => {
match identifier {
COMPACT_EXTENDED_IDENTIFIER_FLAG => (
{
let extended_identifier = buf.get_u8();
match extended_identifier {
TRANSFER_TX_TYPE_ID => Self::Custom,
PAYMENT_TX_TYPE_ID => Self::Payment,
_ => panic!("Unsupported TxType identifier: {extended_identifier}"),
}
}
_ => panic!("Unknown identifier for TxType: {identifier}"),
},
buf,
)
},
buf,
),
v => Self::from_compact(buf, v),
}
}
}