Skip to content

Commit

Permalink
feat: refactor request builder workflow (alloy-rs#431)
Browse files Browse the repository at this point in the history
* feat: refactor request builder workflow

* feat: return all tx builder errors in one invocation

* fix: avoid nesting

* feat: move get_invalid_*_fields() to TransactionRequest

* feat: Impl Display for TxType

* feat: (wip) get info about transaction type currently building

* wip: refactor refactor refactor

* feat: tx type in trait

* fix: core fmt

* fix: tests passing

* fix: no_std in consensus

* feature: assert_preferred

* fix: anytxtype

---------

Co-authored-by: James <james@prestwi.ch>
  • Loading branch information
2 people authored and ben186 committed Jul 27, 2024
1 parent 6c7c857 commit 17ff9ac
Show file tree
Hide file tree
Showing 13 changed files with 694 additions and 164 deletions.
19 changes: 19 additions & 0 deletions crates/consensus/src/transaction/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::fmt;

use crate::{
Signed, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEip4844WithSidecar, TxLegacy,
};
Expand All @@ -24,6 +26,23 @@ pub enum TxType {
Eip4844 = 3,
}

impl From<TxType> for u8 {
fn from(value: TxType) -> Self {
value as u8
}
}

impl fmt::Display for TxType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TxType::Legacy => write!(f, "Legacy"),
TxType::Eip2930 => write!(f, "EIP-2930"),
TxType::Eip1559 => write!(f, "EIP-1559"),
TxType::Eip4844 => write!(f, "EIP-4844"),
}
}
}

#[cfg(any(test, feature = "arbitrary"))]
impl<'a> arbitrary::Arbitrary<'a> for TxType {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
Expand Down
17 changes: 16 additions & 1 deletion crates/consensus/src/transaction/typed.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{Transaction, TxEip1559, TxEip2930, TxEip4844Variant, TxEnvelope, TxLegacy, TxType};
use crate::{
Transaction, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEip4844WithSidecar,
TxEnvelope, TxLegacy, TxType,
};
use alloy_primitives::TxKind;

/// The TypedTransaction enum represents all Ethereum transaction request types.
Expand Down Expand Up @@ -50,6 +53,18 @@ impl From<TxEip4844Variant> for TypedTransaction {
}
}

impl From<TxEip4844> for TypedTransaction {
fn from(tx: TxEip4844) -> Self {
Self::Eip4844(tx.into())
}
}

impl From<TxEip4844WithSidecar> for TypedTransaction {
fn from(tx: TxEip4844WithSidecar) -> Self {
Self::Eip4844(tx.into())
}
}

impl From<TxEnvelope> for TypedTransaction {
fn from(envelope: TxEnvelope) -> Self {
match envelope {
Expand Down
32 changes: 26 additions & 6 deletions crates/network/src/any/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ use std::ops::{Deref, DerefMut};
use alloy_consensus::BlobTransactionSidecar;
use alloy_rpc_types::{AccessList, TransactionRequest, WithOtherFields};

use crate::{
any::AnyNetwork, ethereum::build_unsigned, BuilderResult, Network, TransactionBuilder,
};
use crate::{any::AnyNetwork, BuildResult, Network, TransactionBuilder, TransactionBuilderError};

impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
fn chain_id(&self) -> Option<alloy_primitives::ChainId> {
Expand Down Expand Up @@ -114,6 +112,10 @@ impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
self.deref_mut().set_blob_sidecar(sidecar)
}

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"])?)
}

fn can_build(&self) -> bool {
self.deref().can_build()
}
Expand All @@ -122,14 +124,32 @@ impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
self.deref().can_submit()
}

fn build_unsigned(self) -> BuilderResult<<AnyNetwork as Network>::UnsignedTx> {
build_unsigned::<AnyNetwork>(self.inner)
fn output_tx_type(&self) -> <AnyNetwork as Network>::TxType {
self.deref().output_tx_type().into()
}

fn output_tx_type_checked(&self) -> Option<<AnyNetwork as Network>::TxType> {
self.deref().output_tx_type_checked().map(Into::into)
}

fn prep_for_submission(&mut self) {
self.deref_mut().prep_for_submission()
}

fn build_unsigned(self) -> BuildResult<<AnyNetwork as Network>::UnsignedTx, AnyNetwork> {
if let Err((tx_type, missing)) = self.missing_keys() {
return Err((
self,
TransactionBuilderError::InvalidTransactionRequest(tx_type.into(), missing),
));
}
Ok(self.inner.build_typed_tx().expect("checked by missing_keys"))
}

async fn build<S: crate::NetworkSigner<AnyNetwork>>(
self,
signer: &S,
) -> BuilderResult<alloy_consensus::TxEnvelope> {
) -> Result<<AnyNetwork as Network>::TxEnvelope, TransactionBuilderError<AnyNetwork>> {
Ok(signer.sign_request(self).await?)
}
}
43 changes: 43 additions & 0 deletions crates/network/src/any/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,51 @@
use core::fmt;

use crate::{Network, ReceiptResponse};
use alloy_consensus::TxType;
use alloy_eips::eip2718::Eip2718Error;
use alloy_rpc_types::{
AnyTransactionReceipt, Header, Transaction, TransactionRequest, WithOtherFields,
};

mod builder;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AnyTxType(u8);

impl fmt::Display for AnyTxType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "AnyTxType({})", self.0)
}
}

impl TryFrom<u8> for AnyTxType {
type Error = Eip2718Error;

fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(Self(value))
}
}

impl From<AnyTxType> for u8 {
fn from(value: AnyTxType) -> Self {
value.0
}
}

impl TryFrom<AnyTxType> for TxType {
type Error = Eip2718Error;

fn try_from(value: AnyTxType) -> Result<Self, Self::Error> {
value.0.try_into()
}
}

impl From<TxType> for AnyTxType {
fn from(value: TxType) -> Self {
Self(value as u8)
}
}

/// Types for a catch-all network.
///
/// Essentially just returns the regular Ethereum types + a catch all field.
Expand All @@ -16,6 +57,8 @@ pub struct AnyNetwork {
}

impl Network for AnyNetwork {
type TxType = AnyTxType;

type TxEnvelope = alloy_consensus::TxEnvelope;

type UnsignedTx = alloy_consensus::TypedTransaction;
Expand Down
Loading

0 comments on commit 17ff9ac

Please sign in to comment.