Skip to content

Commit

Permalink
feat(rpc): Replace TypedTransactionType (paradigmxyz#11089)
Browse files Browse the repository at this point in the history
Co-authored-by: Matthias Seitz <[email protected]>
  • Loading branch information
Jennifer and mattsse authored Sep 25, 2024
1 parent 466f21a commit 5d2867f
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 413 deletions.
11 changes: 3 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/rpc/rpc-eth-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ reth-evm.workspace = true
reth-primitives.workspace = true
reth-provider.workspace = true
reth-revm.workspace = true
reth-rpc-types.workspace = true
reth-rpc-types-compat.workspace = true
reth-tasks = { workspace = true, features = ["rayon"] }
reth-transaction-pool.workspace = true
Expand Down
9 changes: 4 additions & 5 deletions crates/rpc/rpc-eth-api/src/helpers/signer.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
//! An abstraction over ethereum signers.
use std::result;

use alloy_dyn_abi::TypedData;
use alloy_primitives::Address;
use alloy_rpc_types_eth::TransactionRequest;
use dyn_clone::DynClone;
use reth_primitives::{Signature, TransactionSigned};
use reth_rpc_eth_types::SignError;
use reth_rpc_types::TypedTransactionRequest;
use std::result;

/// Result returned by [`EthSigner`] methods.
pub type Result<T> = result::Result<T, SignError>;
Expand All @@ -27,9 +26,9 @@ pub trait EthSigner: Send + Sync + DynClone {
async fn sign(&self, address: Address, message: &[u8]) -> Result<Signature>;

/// signs a transaction request using the given account in request
fn sign_transaction(
async fn sign_transaction(
&self,
request: TypedTransactionRequest,
request: TransactionRequest,
address: &Address,
) -> Result<TransactionSigned>;

Expand Down
193 changes: 16 additions & 177 deletions crates/rpc/rpc-eth-api/src/helpers/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
//! network.
use alloy_dyn_abi::TypedData;
use alloy_primitives::{Address, Bytes, TxHash, TxKind, B256, U256};
use alloy_network::TransactionBuilder;
use alloy_primitives::{Address, Bytes, TxHash, B256};
use alloy_rpc_types::{BlockNumberOrTag, TransactionInfo};
use alloy_rpc_types_eth::transaction::TransactionRequest;
use futures::Future;
Expand All @@ -14,13 +15,6 @@ use reth_rpc_eth_types::{
utils::{binary_search, recover_raw_transaction},
EthApiError, EthStateCache, SignError, TransactionSource,
};
use reth_rpc_types::{
transaction::{
EIP1559TransactionRequest, EIP2930TransactionRequest, EIP4844TransactionRequest,
LegacyTransactionRequest,
},
TypedTransactionRequest,
};
use reth_rpc_types_compat::transaction::{from_recovered, from_recovered_with_block_context};
use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool};

Expand Down Expand Up @@ -369,172 +363,14 @@ pub trait EthTransactions: LoadTransaction {
}

let chain_id = self.chain_id();
request.chain_id = Some(chain_id.to::<u64>());

let estimated_gas =
self.estimate_gas_at(request.clone(), BlockId::pending(), None).await?;
let gas_limit = estimated_gas;
request.set_gas_limit(gas_limit.to::<u128>());

let TransactionRequest {
to,
gas_price,
max_fee_per_gas,
max_priority_fee_per_gas,
gas,
value,
input: data,
nonce,
mut access_list,
max_fee_per_blob_gas,
blob_versioned_hashes,
sidecar,
..
} = request;

// todo: remove this inlining after https://github.com/alloy-rs/alloy/pull/183#issuecomment-1928161285
let transaction = match (
gas_price,
max_fee_per_gas,
access_list.take(),
max_fee_per_blob_gas,
blob_versioned_hashes,
sidecar,
) {
// legacy transaction
// gas price required
(Some(_), None, None, None, None, None) => {
Some(TypedTransactionRequest::Legacy(LegacyTransactionRequest {
nonce: nonce.unwrap_or_default(),
gas_price: U256::from(gas_price.unwrap_or_default()),
gas_limit: U256::from(gas.unwrap_or_default()),
value: value.unwrap_or_default(),
input: data.into_input().unwrap_or_default(),
kind: to.unwrap_or(TxKind::Create),
chain_id: None,
}))
}
// EIP2930
// if only accesslist is set, and no eip1599 fees
(_, None, Some(access_list), None, None, None) => {
Some(TypedTransactionRequest::EIP2930(EIP2930TransactionRequest {
nonce: nonce.unwrap_or_default(),
gas_price: U256::from(gas_price.unwrap_or_default()),
gas_limit: U256::from(gas.unwrap_or_default()),
value: value.unwrap_or_default(),
input: data.into_input().unwrap_or_default(),
kind: to.unwrap_or(TxKind::Create),
chain_id: 0,
access_list,
}))
}
// EIP1559
// if 4844 fields missing
// gas_price, max_fee_per_gas, access_list, max_fee_per_blob_gas,
// blob_versioned_hashes, sidecar,
(None, _, _, None, None, None) => {
// Empty fields fall back to the canonical transaction schema.
Some(TypedTransactionRequest::EIP1559(EIP1559TransactionRequest {
nonce: nonce.unwrap_or_default(),
max_fee_per_gas: U256::from(max_fee_per_gas.unwrap_or_default()),
max_priority_fee_per_gas: U256::from(
max_priority_fee_per_gas.unwrap_or_default(),
),
gas_limit: U256::from(gas.unwrap_or_default()),
value: value.unwrap_or_default(),
input: data.into_input().unwrap_or_default(),
kind: to.unwrap_or(TxKind::Create),
chain_id: 0,
access_list: access_list.unwrap_or_default(),
}))
}
// EIP4884
// all blob fields required
(
None,
_,
_,
Some(max_fee_per_blob_gas),
Some(blob_versioned_hashes),
Some(sidecar),
) => {
// As per the EIP, we follow the same semantics as EIP-1559.
Some(TypedTransactionRequest::EIP4844(EIP4844TransactionRequest {
chain_id: 0,
nonce: nonce.unwrap_or_default(),
max_priority_fee_per_gas: U256::from(
max_priority_fee_per_gas.unwrap_or_default(),
),
max_fee_per_gas: U256::from(max_fee_per_gas.unwrap_or_default()),
gas_limit: U256::from(gas.unwrap_or_default()),
value: value.unwrap_or_default(),
input: data.into_input().unwrap_or_default(),
to: match to {
Some(TxKind::Call(to)) => to,
_ => Address::default(),
},
access_list: access_list.unwrap_or_default(),

// eip-4844 specific.
max_fee_per_blob_gas: U256::from(max_fee_per_blob_gas),
blob_versioned_hashes,
sidecar,
}))
}

_ => None,
};

let transaction = match transaction {
Some(TypedTransactionRequest::Legacy(mut req)) => {
req.chain_id = Some(chain_id.to());
req.gas_limit = gas_limit.saturating_to();
req.gas_price = self.legacy_gas_price(gas_price.map(U256::from)).await?;

TypedTransactionRequest::Legacy(req)
}
Some(TypedTransactionRequest::EIP2930(mut req)) => {
req.chain_id = chain_id.to();
req.gas_limit = gas_limit.saturating_to();
req.gas_price = self.legacy_gas_price(gas_price.map(U256::from)).await?;

TypedTransactionRequest::EIP2930(req)
}
Some(TypedTransactionRequest::EIP1559(mut req)) => {
let (max_fee_per_gas, max_priority_fee_per_gas) = self
.eip1559_fees(
max_fee_per_gas.map(U256::from),
max_priority_fee_per_gas.map(U256::from),
)
.await?;

req.chain_id = chain_id.to();
req.gas_limit = gas_limit.saturating_to();
req.max_fee_per_gas = max_fee_per_gas.saturating_to();
req.max_priority_fee_per_gas = max_priority_fee_per_gas.saturating_to();

TypedTransactionRequest::EIP1559(req)
}
Some(TypedTransactionRequest::EIP4844(mut req)) => {
let (max_fee_per_gas, max_priority_fee_per_gas) = self
.eip1559_fees(
max_fee_per_gas.map(U256::from),
max_priority_fee_per_gas.map(U256::from),
)
.await?;

req.max_fee_per_gas = max_fee_per_gas;
req.max_priority_fee_per_gas = max_priority_fee_per_gas;
req.max_fee_per_blob_gas =
self.eip4844_blob_fee(max_fee_per_blob_gas.map(U256::from)).await?;

req.chain_id = chain_id.to();
req.gas_limit = gas_limit;

TypedTransactionRequest::EIP4844(req)
}
None => return Err(EthApiError::ConflictingFeeFieldsInRequest.into()),
};

let signed_tx = self.sign_request(&from, transaction)?;
let signed_tx = self.sign_request(&from, request).await?;

let recovered =
signed_tx.into_ecrecovered().ok_or(EthApiError::InvalidTransactionSignature)?;
Expand All @@ -555,17 +391,20 @@ pub trait EthTransactions: LoadTransaction {
fn sign_request(
&self,
from: &Address,
request: TypedTransactionRequest,
) -> Result<TransactionSigned, Self::Error> {
for signer in self.signers().read().iter() {
if signer.is_signer_for(from) {
return match signer.sign_transaction(request, from) {
Ok(tx) => Ok(tx),
Err(e) => Err(e.into_eth_err()),
txn: TransactionRequest,
) -> impl Future<Output = Result<TransactionSigned, Self::Error>> + Send {
async move {
let signers: Vec<_> = self.signers().read().iter().cloned().collect();
for signer in signers {
if signer.is_signer_for(from) {
return match signer.sign_transaction(txn, from).await {
Ok(tx) => Ok(tx),
Err(e) => Err(e.into_eth_err()),
}
}
}
Err(EthApiError::InvalidTransactionSignature.into())
}
Err(EthApiError::InvalidTransactionSignature.into())
}

/// Signs given message. Returns the signature.
Expand Down
4 changes: 0 additions & 4 deletions crates/rpc/rpc-types-compat/src/transaction/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
//! Compatibility functions for rpc `Transaction` type.
mod signature;
mod typed;

pub use signature::*;
pub use typed::*;

use std::fmt;

use alloy_rpc_types::{
Expand Down
58 changes: 0 additions & 58 deletions crates/rpc/rpc-types-compat/src/transaction/typed.rs

This file was deleted.

Loading

0 comments on commit 5d2867f

Please sign in to comment.