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

Add supertrait alloy_consensus::Transaction to RPC TransactionResponse #1387

Merged
merged 9 commits into from
Sep 30, 2024
63 changes: 63 additions & 0 deletions crates/consensus/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,66 @@ impl<S: 'static> dyn SignableTransaction<S> {
}
}
}

#[cfg(feature = "serde")]
impl<T: Transaction> Transaction for alloy_serde::WithOtherFields<T> {
fn chain_id(&self) -> Option<ChainId> {
self.inner.chain_id()
}

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

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

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

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

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

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

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

fn to(&self) -> TxKind {
self.inner.to()
}

fn value(&self) -> U256 {
self.inner.value()
}

fn input(&self) -> &[u8] {
self.inner.input()
}

fn ty(&self) -> u8 {
self.inner.ty()
}

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

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

fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
self.inner.authorization_list()
}
}
1 change: 1 addition & 0 deletions crates/network-primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ workspace = true
alloy-primitives.workspace = true
alloy-serde.workspace = true
alloy-eips.workspace = true
alloy-consensus = { workspace = true, features = ["serde"] }

serde.workspace = true

Expand Down
132 changes: 32 additions & 100 deletions crates/network-primitives/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use alloc::vec::Vec;
use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization};
use alloy_primitives::{Address, BlockHash, Bytes, ChainId, TxHash, B256, U256};
use alloy_consensus::Transaction;
use alloy_eips::eip7702::SignedAuthorization;
use alloy_primitives::{Address, BlockHash, Bytes, TxHash, B256, U256};
use alloy_serde::WithOtherFields;

use crate::BlockTransactions;
Expand Down Expand Up @@ -62,17 +62,15 @@ pub trait ReceiptResponse {
fn state_root(&self) -> Option<B256>;
}

/// Transaction JSON-RPC response.
pub trait TransactionResponse {
/// Transaction JSON-RPC response. Aggregates transaction data with its block and signer context.
pub trait TransactionResponse: Transaction {
/// Signature type of the transaction
type Signature;

/// Hash of the transaction
#[doc(alias = "transaction_hash")]
fn tx_hash(&self) -> TxHash;

/// Nonce
fn nonce(&self) -> u64;

/// Block hash
fn block_hash(&self) -> Option<BlockHash>;

Expand All @@ -85,48 +83,38 @@ pub trait TransactionResponse {
/// Sender of the transaction
fn from(&self) -> Address;

/// Recipient of the transaction
fn to(&self) -> Option<Address>;

/// Transferred value
fn value(&self) -> U256;

/// Gas Price
fn gas_price(&self) -> Option<u128>;

/// Gas limit
fn gas(&self) -> u64;

/// Max BaseFeePerGas the user is willing to pay
fn max_fee_per_gas(&self) -> Option<u128>;

/// The miner's tip
fn max_priority_fee_per_gas(&self) -> Option<u128>;
/// Recipient of the transaction. Returns `None`if transaction is a contract creation.
emhane marked this conversation as resolved.
Show resolved Hide resolved
fn to(&self) -> Option<Address> {
Transaction::to(self).to().copied()
}

/// Configured max fee per blob gas for eip-4844 transactions
fn max_fee_per_blob_gas(&self) -> Option<u128>;
/// Gas Price, this is the RPC format for `max_fee_per_gas`, pre-eip-1559.
fn gas_price(&self) -> Option<u128> {
if self.ty() < 2 {
return Some(Transaction::max_fee_per_gas(self));
}
None
}

/// Input data
#[doc(alias = "calldata")]
fn input(&self) -> &Bytes;
/// Max BaseFeePerGas the user is willing to pay. For pre-eip-1559 transactions, the field
/// label `gas_price` is used instead.
fn max_fee_per_gas(&self) -> Option<u128> {
if self.ty() < 2 {
return None;
}
Some(Transaction::max_fee_per_gas(self))
}

/// Transaction signature
fn signature(&self) -> Option<Self::Signature>;

/// The chain id of the transaction
fn chain_id(&self) -> Option<ChainId>;

/// Contains the blob hashes for eip-4844 transactions
fn blob_versioned_hashes(&self) -> Option<Vec<B256>>;

/// EIP2930 access list
fn access_list(&self) -> Option<AccessList>;

/// Transaction type
fn transaction_type(&self) -> Option<u8>;

/// The signed authorization list
fn authorization_list(&self) -> Option<Vec<SignedAuthorization>>;
/// Transaction type format for RPC. This field is included since eip-2930.
fn transaction_type(&self) -> Option<u8> {
match self.ty() {
0 => None,
ty => Some(ty),
}
}
}

/// Header JSON-RPC response.
Expand Down Expand Up @@ -203,10 +191,6 @@ impl<T: TransactionResponse> TransactionResponse for WithOtherFields<T> {
self.inner.tx_hash()
}

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

fn block_hash(&self) -> Option<BlockHash> {
self.inner.block_hash()
}
Expand All @@ -223,61 +207,9 @@ impl<T: TransactionResponse> TransactionResponse for WithOtherFields<T> {
self.inner.from()
}

fn to(&self) -> Option<Address> {
self.inner.to()
}

fn value(&self) -> U256 {
self.inner.value()
}

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

fn gas(&self) -> u64 {
self.inner.gas()
}

fn max_fee_per_gas(&self) -> Option<u128> {
self.inner.max_fee_per_gas()
}

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

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

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

fn signature(&self) -> Option<T::Signature> {
self.inner.signature()
}

fn chain_id(&self) -> Option<ChainId> {
self.inner.chain_id()
}

fn blob_versioned_hashes(&self) -> Option<Vec<B256>> {
self.inner.blob_versioned_hashes()
}

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

fn transaction_type(&self) -> Option<u8> {
self.inner.transaction_type()
}

fn authorization_list(&self) -> Option<Vec<SignedAuthorization>> {
self.inner.authorization_list()
}
}

impl<T: ReceiptResponse> ReceiptResponse for WithOtherFields<T> {
Expand Down
90 changes: 50 additions & 40 deletions crates/rpc-types-eth/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,87 +338,97 @@ impl TryFrom<Transaction> for TxEnvelope {
}
}

impl TransactionResponse for Transaction {
type Signature = Signature;

fn tx_hash(&self) -> B256 {
self.hash
impl alloy_consensus::Transaction for Transaction {
fn chain_id(&self) -> Option<ChainId> {
self.chain_id
}

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

fn block_hash(&self) -> Option<BlockHash> {
self.block_hash
fn gas_limit(&self) -> u64 {
self.gas
}

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

fn transaction_index(&self) -> Option<u64> {
self.transaction_index
fn max_fee_per_gas(&self) -> u128 {
self.max_fee_per_gas.unwrap_or(self.gas_price.unwrap_or_default())
}

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

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

fn to(&self) -> Option<Address> {
self.to
fn priority_fee_or_price(&self) -> u128 {
debug_assert!(
self.max_fee_per_gas.is_some() || self.gas_price.is_some(),
"mutually exclusive fields"
);
self.max_fee_per_gas.unwrap_or(self.gas_price.unwrap_or_default())
}

fn to(&self) -> TxKind {
self.to.into()
}

fn value(&self) -> U256 {
self.value
}

fn gas_price(&self) -> Option<u128> {
self.gas_price
fn input(&self) -> &[u8] {
&self.input
}

fn gas(&self) -> u64 {
self.gas
fn ty(&self) -> u8 {
self.transaction_type.unwrap_or_default()
}

fn max_fee_per_gas(&self) -> Option<u128> {
self.max_fee_per_gas
fn access_list(&self) -> Option<&AccessList> {
self.access_list.as_ref()
}

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

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

fn input(&self) -> &Bytes {
&self.input
}
impl TransactionResponse for Transaction {
type Signature = Signature;

fn signature(&self) -> Option<Signature> {
self.signature
fn tx_hash(&self) -> B256 {
self.hash
}

fn chain_id(&self) -> Option<ChainId> {
self.chain_id
fn block_hash(&self) -> Option<BlockHash> {
self.block_hash
}

fn blob_versioned_hashes(&self) -> Option<Vec<B256>> {
self.blob_versioned_hashes.clone()
fn block_number(&self) -> Option<u64> {
self.block_number
}

fn access_list(&self) -> Option<AccessList> {
self.access_list.clone()
fn transaction_index(&self) -> Option<u64> {
self.transaction_index
}

fn transaction_type(&self) -> Option<u8> {
self.transaction_type
fn from(&self) -> Address {
self.from
}

fn authorization_list(&self) -> Option<Vec<SignedAuthorization>> {
self.authorization_list.clone()
fn signature(&self) -> Option<Signature> {
self.signature
}
}

Expand Down
Loading