Skip to content

Commit

Permalink
refactor: separate transaction builders for tx types (#1259)
Browse files Browse the repository at this point in the history
* refactor: txtype-specific transaction builders

* enforce legacy if access list

* ignore access list
  • Loading branch information
klkvr authored Sep 17, 2024
1 parent 4e8f429 commit 099e64d
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 191 deletions.
12 changes: 9 additions & 3 deletions crates/contract/src/call.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{CallDecoder, Error, EthCall, Result};
use alloy_dyn_abi::{DynSolValue, JsonAbiExt};
use alloy_json_abi::Function;
use alloy_network::{Ethereum, Network, TransactionBuilder};
use alloy_network::{Ethereum, Network, TransactionBuilder, TransactionBuilder4844};
use alloy_network_primitives::ReceiptResponse;
use alloy_primitives::{Address, Bytes, ChainId, TxKind, U256};
use alloy_provider::{PendingTransactionBuilder, Provider};
Expand Down Expand Up @@ -334,7 +334,10 @@ impl<T: Transport + Clone, P: Provider<T, N>, D: CallDecoder, N: Network> CallBu
}

/// Sets the `sidecar` field in the transaction to the provided value.
pub fn sidecar(mut self, blob_sidecar: BlobTransactionSidecar) -> Self {
pub fn sidecar(mut self, blob_sidecar: BlobTransactionSidecar) -> Self
where
N::TransactionRequest: TransactionBuilder4844,
{
self.request.set_blob_sidecar(blob_sidecar);
self
}
Expand Down Expand Up @@ -371,7 +374,10 @@ impl<T: Transport + Clone, P: Provider<T, N>, D: CallDecoder, N: Network> CallBu
}

/// Sets the `max_fee_per_blob_gas` in the transaction to the provided value
pub fn max_fee_per_blob_gas(mut self, max_fee_per_blob_gas: u128) -> Self {
pub fn max_fee_per_blob_gas(mut self, max_fee_per_blob_gas: u128) -> Self
where
N::TransactionRequest: TransactionBuilder4844,
{
self.request.set_max_fee_per_blob_gas(max_fee_per_blob_gas);
self
}
Expand Down
54 changes: 29 additions & 25 deletions crates/network/src/any/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
any::AnyNetwork, BuildResult, Network, NetworkWallet, TransactionBuilder,
TransactionBuilderError,
TransactionBuilder4844, TransactionBuilder7702, TransactionBuilderError,
};
use alloy_consensus::BlobTransactionSidecar;
use alloy_eips::eip7702::SignedAuthorization;
Expand Down Expand Up @@ -86,14 +86,6 @@ impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
self.deref_mut().set_max_priority_fee_per_gas(max_priority_fee_per_gas);
}

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

fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) {
self.deref_mut().set_max_fee_per_blob_gas(max_fee_per_blob_gas)
}

fn gas_limit(&self) -> Option<u128> {
self.deref().gas_limit()
}
Expand All @@ -112,22 +104,6 @@ impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
self.deref_mut().set_access_list(access_list)
}

fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar> {
self.deref().blob_sidecar()
}

fn set_blob_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
self.deref_mut().set_blob_sidecar(sidecar)
}

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

fn set_authorization_list(&mut self, authorization_list: Vec<SignedAuthorization>) {
self.deref_mut().set_authorization_list(authorization_list)
}

fn complete_type(&self, ty: <AnyNetwork as Network>::TxType) -> Result<(), Vec<&'static str>> {
self.deref().complete_type(ty.try_into().map_err(|_| vec!["supported tx type"])?)
}
Expand Down Expand Up @@ -172,3 +148,31 @@ impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
Ok(wallet.sign_request(self).await?)
}
}

impl TransactionBuilder4844 for WithOtherFields<TransactionRequest> {
fn max_fee_per_blob_gas(&self) -> Option<u128> {
self.deref().max_fee_per_blob_gas()
}

fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) {
self.deref_mut().set_max_fee_per_blob_gas(max_fee_per_blob_gas)
}

fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar> {
self.deref().blob_sidecar()
}

fn set_blob_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
self.deref_mut().set_blob_sidecar(sidecar)
}
}

impl TransactionBuilder7702 for WithOtherFields<TransactionRequest> {
fn authorization_list(&self) -> Option<&Vec<SignedAuthorization>> {
self.deref().authorization_list()
}

fn set_authorization_list(&mut self, authorization_list: Vec<SignedAuthorization>) {
self.deref_mut().set_authorization_list(authorization_list)
}
}
61 changes: 34 additions & 27 deletions crates/network/src/ethereum/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
BuildResult, Ethereum, Network, NetworkWallet, TransactionBuilder, TransactionBuilderError,
BuildResult, Ethereum, Network, NetworkWallet, TransactionBuilder, TransactionBuilder4844,
TransactionBuilder7702, TransactionBuilderError,
};
use alloy_consensus::{BlobTransactionSidecar, TxType, TypedTransaction};
use alloy_eips::eip7702::SignedAuthorization;
Expand Down Expand Up @@ -83,14 +84,6 @@ impl TransactionBuilder<Ethereum> for TransactionRequest {
self.max_priority_fee_per_gas = Some(max_priority_fee_per_gas);
}

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

fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) {
self.max_fee_per_blob_gas = Some(max_fee_per_blob_gas)
}

fn gas_limit(&self) -> Option<u128> {
self.gas
}
Expand All @@ -107,23 +100,6 @@ impl TransactionBuilder<Ethereum> for TransactionRequest {
self.access_list = Some(access_list);
}

fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar> {
self.sidecar.as_ref()
}

fn set_blob_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
self.sidecar = Some(sidecar);
self.populate_blob_hashes();
}

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

fn set_authorization_list(&mut self, authorization_list: Vec<SignedAuthorization>) {
self.authorization_list = Some(authorization_list);
}

fn complete_type(&self, ty: TxType) -> Result<(), Vec<&'static str>> {
match ty {
TxType::Legacy => self.complete_legacy(),
Expand Down Expand Up @@ -191,9 +167,40 @@ impl TransactionBuilder<Ethereum> for TransactionRequest {
}
}

impl TransactionBuilder4844 for TransactionRequest {
fn max_fee_per_blob_gas(&self) -> Option<u128> {
self.max_fee_per_blob_gas
}

fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) {
self.max_fee_per_blob_gas = Some(max_fee_per_blob_gas)
}

fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar> {
self.sidecar.as_ref()
}

fn set_blob_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
self.sidecar = Some(sidecar);
self.populate_blob_hashes();
}
}

impl TransactionBuilder7702 for TransactionRequest {
fn authorization_list(&self) -> Option<&Vec<SignedAuthorization>> {
self.authorization_list.as_ref()
}

fn set_authorization_list(&mut self, authorization_list: Vec<SignedAuthorization>) {
self.authorization_list = Some(authorization_list);
}
}

#[cfg(test)]
mod tests {
use crate::{TransactionBuilder, TransactionBuilderError};
use crate::{
TransactionBuilder, TransactionBuilder4844, TransactionBuilder7702, TransactionBuilderError,
};
use alloy_consensus::{BlobTransactionSidecar, TxEip1559, TxType, TypedTransaction};
use alloy_eips::eip7702::Authorization;
use alloy_primitives::{Address, Signature, U256};
Expand Down
4 changes: 2 additions & 2 deletions crates/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use core::fmt::{Debug, Display};

mod transaction;
pub use transaction::{
BuildResult, NetworkWallet, TransactionBuilder, TransactionBuilderError, TxSigner,
TxSignerSync, UnbuiltTransactionError,
BuildResult, NetworkWallet, TransactionBuilder, TransactionBuilder4844, TransactionBuilder7702,
TransactionBuilderError, TxSigner, TxSignerSync, UnbuiltTransactionError,
};

mod ethereum;
Expand Down
85 changes: 45 additions & 40 deletions crates/network/src/transaction/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,19 +248,6 @@ pub trait TransactionBuilder<N: Network>: Default + Sized + Send + Sync + 'stati
self.set_max_priority_fee_per_gas(max_priority_fee_per_gas);
self
}

/// Get the max fee per blob gas for the transaction.
fn max_fee_per_blob_gas(&self) -> Option<u128>;

/// Set the max fee per blob gas for the transaction.
fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128);

/// Builder-pattern method for setting max fee per blob gas .
fn with_max_fee_per_blob_gas(mut self, max_fee_per_blob_gas: u128) -> Self {
self.set_max_fee_per_blob_gas(max_fee_per_blob_gas);
self
}

/// Get the gas limit for the transaction.
fn gas_limit(&self) -> Option<u128>;

Expand All @@ -285,33 +272,6 @@ pub trait TransactionBuilder<N: Network>: Default + Sized + Send + Sync + 'stati
self
}

/// Gets the EIP-4844 blob sidecar of the transaction.
fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar>;

/// Sets the EIP-4844 blob sidecar of the transaction.
///
/// Note: This will also set the versioned blob hashes accordingly:
/// [BlobTransactionSidecar::versioned_hashes]
fn set_blob_sidecar(&mut self, sidecar: BlobTransactionSidecar);

/// Builder-pattern method for setting the EIP-4844 blob sidecar of the transaction.
fn with_blob_sidecar(mut self, sidecar: BlobTransactionSidecar) -> Self {
self.set_blob_sidecar(sidecar);
self
}

/// Get the EIP-7702 authorization list for the transaction.
fn authorization_list(&self) -> Option<&Vec<SignedAuthorization>>;

/// Sets the EIP-7702 authorization list.
fn set_authorization_list(&mut self, authorization_list: Vec<SignedAuthorization>);

/// Builder-pattern method for setting the authorization list.
fn with_authorization_list(mut self, authorization_list: Vec<SignedAuthorization>) -> Self {
self.set_authorization_list(authorization_list);
self
}

/// Check if all necessary keys are present to build the specified type,
/// returning a list of missing keys.
fn complete_type(&self, ty: N::TxType) -> Result<(), Vec<&'static str>>;
Expand Down Expand Up @@ -383,3 +343,48 @@ pub trait TransactionBuilder<N: Network>: Default + Sized + Send + Sync + 'stati
wallet: &W,
) -> impl_future!(<Output = Result<N::TxEnvelope, TransactionBuilderError<N>>>);
}

/// Transaction builder type supporting EIP-4844 transaction fields.
pub trait TransactionBuilder4844: Default + Sized + Send + Sync + 'static {
/// Get the max fee per blob gas for the transaction.
fn max_fee_per_blob_gas(&self) -> Option<u128>;

/// Set the max fee per blob gas for the transaction.
fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128);

/// Builder-pattern method for setting max fee per blob gas .
fn with_max_fee_per_blob_gas(mut self, max_fee_per_blob_gas: u128) -> Self {
self.set_max_fee_per_blob_gas(max_fee_per_blob_gas);
self
}

/// Gets the EIP-4844 blob sidecar of the transaction.
fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar>;

/// Sets the EIP-4844 blob sidecar of the transaction.
///
/// Note: This will also set the versioned blob hashes accordingly:
/// [BlobTransactionSidecar::versioned_hashes]
fn set_blob_sidecar(&mut self, sidecar: BlobTransactionSidecar);

/// Builder-pattern method for setting the EIP-4844 blob sidecar of the transaction.
fn with_blob_sidecar(mut self, sidecar: BlobTransactionSidecar) -> Self {
self.set_blob_sidecar(sidecar);
self
}
}

/// Transaction builder type supporting EIP-7702 transaction fields.
pub trait TransactionBuilder7702: Default + Sized + Send + Sync + 'static {
/// Get the EIP-7702 authorization list for the transaction.
fn authorization_list(&self) -> Option<&Vec<SignedAuthorization>>;

/// Sets the EIP-7702 authorization list.
fn set_authorization_list(&mut self, authorization_list: Vec<SignedAuthorization>);

/// Builder-pattern method for setting the authorization list.
fn with_authorization_list(mut self, authorization_list: Vec<SignedAuthorization>) -> Self {
self.set_authorization_list(authorization_list);
self
}
}
3 changes: 2 additions & 1 deletion crates/network/src/transaction/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod builder;
pub use builder::{
BuildResult, TransactionBuilder, TransactionBuilderError, UnbuiltTransactionError,
BuildResult, TransactionBuilder, TransactionBuilder4844, TransactionBuilder7702,
TransactionBuilderError, UnbuiltTransactionError,
};

mod signer;
Expand Down
11 changes: 8 additions & 3 deletions crates/provider/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
fillers::{
CachedNonceManager, ChainIdFiller, FillerControlFlow, GasFiller, JoinFill, NonceFiller,
NonceManager, RecommendedFiller, SimpleNonceManager, TxFiller, WalletFiller,
NonceManager, RecommendedFillers, SimpleNonceManager, TxFiller, WalletFiller,
},
provider::SendableTx,
Provider, RootProvider,
Expand Down Expand Up @@ -130,8 +130,13 @@ impl<N> Default for ProviderBuilder<Identity, Identity, N> {
impl<L, N> ProviderBuilder<L, Identity, N> {
/// Add preconfigured set of layers handling gas estimation, nonce
/// management, and chain-id fetching.
pub fn with_recommended_fillers(self) -> ProviderBuilder<L, RecommendedFiller, N> {
self.filler(GasFiller).filler(NonceFiller::default()).filler(ChainIdFiller::default())
pub fn with_recommended_fillers(
self,
) -> ProviderBuilder<L, JoinFill<Identity, N::RecomendedFillters>, N>
where
N: RecommendedFillers,
{
self.filler(N::recommended_fillers())
}

/// Add gas estimation to the stack being built.
Expand Down
Loading

0 comments on commit 099e64d

Please sign in to comment.