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

refactor: chain-specific provider #603

Merged
merged 13 commits into from
Aug 20, 2024
4 changes: 2 additions & 2 deletions crates/edr_eth/src/eips/eip2718.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ impl<DataT: Receipt<LogT>, LogT> Receipt<LogT> for TypedEnvelope<DataT> {
self.data().logs_bloom()
}

fn logs(&self) -> &[LogT] {
self.data().logs()
fn transaction_logs(&self) -> &[LogT] {
self.data().transaction_logs()
}

fn root_or_status(&self) -> receipt::RootOrStatus<'_> {
Expand Down
2 changes: 1 addition & 1 deletion crates/edr_eth/src/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub trait Receipt<LogT> {
/// Returns the bloom filter of the logs generated within this transaction.
fn logs_bloom(&self) -> &Bloom;
/// Returns the logs generated within this transaction.
fn logs(&self) -> &[LogT];
fn transaction_logs(&self) -> &[LogT];
/// Returns the state root (pre-EIP-658) or status (post-EIP-658) of the
/// receipt.
fn root_or_status(&self) -> RootOrStatus<'_>;
Expand Down
2 changes: 1 addition & 1 deletion crates/edr_eth/src/receipt/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl<LogT> Receipt<LogT> for Execution<LogT> {
}
}

fn logs(&self) -> &[LogT] {
fn transaction_logs(&self) -> &[LogT] {
match self {
Execution::Legacy(receipt) => &receipt.logs,
Execution::Eip658(receipt) => &receipt.logs,
Expand Down
8 changes: 4 additions & 4 deletions crates/edr_eth/src/receipt/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use revm_primitives::{EvmWiring, ExecutionResult, Output};

use super::{MapReceiptLogs, Receipt};
use crate::{
transaction::{SignedTransaction, TransactionType},
transaction::{ExecutableTransaction, Transaction, TransactionType},
Address, Bloom, SpecId, B256, U256,
};

Expand Down Expand Up @@ -52,7 +52,7 @@ impl<ExecutionReceiptT: Receipt<LogT>, LogT> TransactionReceipt<ExecutionReceipt
/// transaction
pub fn new<ChainSpecT>(
execution_receipt: ExecutionReceiptT,
transaction: &impl SignedTransaction,
transaction: &(impl Transaction + ExecutableTransaction),
result: &ExecutionResult<ChainSpecT>,
transaction_index: u64,
block_base_fee: U256,
Expand Down Expand Up @@ -131,8 +131,8 @@ impl<ExecutionReceiptT: Receipt<LogT>, LogT> Receipt<LogT>
self.inner.logs_bloom()
}

fn logs(&self) -> &[LogT] {
self.inner.logs()
fn transaction_logs(&self) -> &[LogT] {
self.inner.transaction_logs()
}

fn root_or_status(&self) -> super::RootOrStatus<'_> {
Expand Down
3 changes: 2 additions & 1 deletion crates/edr_eth/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ mod fakeable;
mod recovery_id;
mod y_parity;

use k256::{elliptic_curve::sec1::ToEncodedPoint, FieldBytes, PublicKey, SecretKey};
pub use k256::SecretKey;
use k256::{elliptic_curve::sec1::ToEncodedPoint, FieldBytes, PublicKey};
use sha3::{Digest, Keccak256};

pub use self::{recovery_id::SignatureWithRecoveryId, y_parity::SignatureWithYParity};
Expand Down
117 changes: 63 additions & 54 deletions crates/edr_eth/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::str::FromStr;
pub use revm_primitives::{alloy_primitives::TxKind, Transaction, TransactionValidation};
use revm_primitives::{ruint, B256};

use crate::{AccessListItem, Address, Bytes, U256, U8};
use crate::{signature::Signature, Bytes, U256, U8};

pub const INVALID_TX_TYPE_ERROR_MESSAGE: &str = "invalid tx type";

Expand Down Expand Up @@ -72,6 +72,18 @@ impl From<Type> for u8 {
}
}

impl IsEip4844 for Type {
fn is_eip4844(&self) -> bool {
matches!(self, Type::Eip4844)
}
}

impl IsLegacy for Type {
fn is_legacy(&self) -> bool {
matches!(self, Type::Legacy)
}
}

#[derive(Debug, thiserror::Error)]
pub enum ParseError {
#[error("{0}")]
Expand Down Expand Up @@ -148,14 +160,15 @@ impl serde::Serialize for Type {
}
}

pub trait SignedTransaction: Transaction + TransactionType {
/// Trait for information about executable transactions.
pub trait ExecutableTransaction {
/// The effective gas price of the transaction, calculated using the
/// provided block base fee. Only applicable for post-EIP-1559 transactions.
fn effective_gas_price(&self, block_base_fee: U256) -> Option<U256>;

/// The maximum fee per gas the sender is willing to pay. Only applicable
/// for post-EIP-1559 transactions.
fn max_fee_per_gas(&self) -> Option<U256>;
fn max_fee_per_gas(&self) -> Option<&U256>;

/// The enveloped (EIP-2718) RLP-encoding of the transaction.
fn rlp_encoding(&self) -> &Bytes;
Expand All @@ -168,71 +181,67 @@ pub trait SignedTransaction: Transaction + TransactionType {
fn transaction_hash(&self) -> &B256;
}

/// Trait for transactions that may be signed.
pub trait MaybeSignedTransaction {
/// Returns the [`Signature`] of the transaction, if any.
fn maybe_signature(&self) -> Option<&dyn Signature>;
}

/// Trait for transactions that have been signed.
pub trait SignedTransaction {
/// Returns the [`Signature`] of the transaction.
fn signature(&self) -> &dyn Signature;
}

impl<TransactionT: SignedTransaction> MaybeSignedTransaction for TransactionT {
fn maybe_signature(&self) -> Option<&dyn Signature> {
Some(self.signature())
}
}

/// Trait for mutable transactions.
pub trait TransactionMut {
/// Sets the gas limit of the transaction.
fn set_gas_limit(&mut self, gas_limit: u64);
}

/// Trait for determining the type of a transaction.
pub trait TransactionType {
/// Type of the transaction.
type Type;
type Type: Into<u8>;

/// Returns the type of the transaction.
fn transaction_type(&self) -> Self::Type;
}

pub fn max_cost(transaction: &impl SignedTransaction) -> U256 {
U256::from(transaction.gas_limit()).saturating_mul(*transaction.gas_price())
/// Trait for determining whether a transaction has an access list.
pub trait HasAccessList {
/// Whether the transaction has an access list.
fn has_access_list(&self) -> bool;
}

pub fn upfront_cost(transaction: &impl SignedTransaction) -> U256 {
max_cost(transaction).saturating_add(*transaction.value())
/// Trait for determining whether a transaction is an EIP-155 transaction.
pub trait IsEip155 {
/// Whether the transaction is an EIP-155 transaction.
fn is_eip155(&self) -> bool;
}

/// Represents _all_ transaction requests received from RPC
#[derive(Clone, Debug, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct EthTransactionRequest {
/// from address
pub from: Address,
/// to address
#[cfg_attr(feature = "serde", serde(default))]
pub to: Option<Address>,
/// legacy, gas Price
#[cfg_attr(feature = "serde", serde(default))]
pub gas_price: Option<U256>,
/// max base fee per gas sender is willing to pay
#[cfg_attr(feature = "serde", serde(default))]
pub max_fee_per_gas: Option<U256>,
/// miner tip
#[cfg_attr(feature = "serde", serde(default))]
pub max_priority_fee_per_gas: Option<U256>,
/// gas
#[cfg_attr(feature = "serde", serde(default, with = "crate::serde::optional_u64"))]
pub gas: Option<u64>,
/// value of th tx in wei
pub value: Option<U256>,
/// Any additional data sent
#[cfg_attr(feature = "serde", serde(alias = "input"))]
pub data: Option<Bytes>,
/// Transaction nonce
#[cfg_attr(feature = "serde", serde(default, with = "crate::serde::optional_u64"))]
pub nonce: Option<u64>,
/// Chain ID
#[cfg_attr(feature = "serde", serde(default, with = "crate::serde::optional_u64"))]
pub chain_id: Option<u64>,
/// warm storage access pre-payment
#[cfg_attr(feature = "serde", serde(default))]
pub access_list: Option<Vec<AccessListItem>>,
/// EIP-2718 type
#[cfg_attr(
feature = "serde",
serde(default, rename = "type", with = "crate::serde::optional_u8")
)]
pub transaction_type: Option<u8>,
/// Blobs (EIP-4844)
pub blobs: Option<Vec<Bytes>>,
/// Blob versioned hashes (EIP-4844)
pub blob_hashes: Option<Vec<B256>>,
/// Trait for determining whether a transaction is an EIP-4844 transaction.
pub trait IsEip4844 {
/// Whether the transaction is an EIP-4844 transaction.
fn is_eip4844(&self) -> bool;
}

/// Trait for determining whether a transaction is a legacy transaction.
pub trait IsLegacy {
/// Whether the transaction is a legacy transaction.
fn is_legacy(&self) -> bool;
}

pub fn max_cost(transaction: &impl Transaction) -> U256 {
U256::from(transaction.gas_limit()).saturating_mul(*transaction.gas_price())
}

pub fn upfront_cost(transaction: &impl Transaction) -> U256 {
max_cost(transaction).saturating_add(*transaction.value())
}
6 changes: 6 additions & 0 deletions crates/edr_eth/src/transaction/fake_signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub(super) mod tests {
() => {
#[test]
fn hash_with_fake_signature_same_sender() {
use $crate::transaction::ExecutableTransaction as _;

let transaction_request = dummy_request();

let sender = Address::from(revm_primitives::ruint::aliases::U160::from(1));
Expand All @@ -19,6 +21,8 @@ pub(super) mod tests {

#[test]
fn hash_with_fake_signature_different_senders() {
use $crate::transaction::ExecutableTransaction as _;

let transaction_request = dummy_request();

let sender_one = Address::from(revm_primitives::ruint::aliases::U160::from(1));
Expand All @@ -35,6 +39,8 @@ pub(super) mod tests {

#[test]
fn recovers_fake_sender() {
use $crate::transaction::Transaction as _;

let transaction_request = dummy_request();

// Fails to recover with signature error if tried to ecrocver a fake signature
Expand Down
Loading
Loading