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

eip4844: use alloy TxEip4844 #10624

Merged
merged 22 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion crates/consensus/common/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ mod tests {
max_priority_fee_per_gas: 0x28f000fff,
max_fee_per_blob_gas: 0x7,
gas_limit: 10,
placeholder: Some(()),
to: Address::default(),
value: U256::from(3_u64),
input: Bytes::from(vec![1, 2]),
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ arbitrary = [
"reth-codec",
]
secp256k1 = ["dep:secp256k1"]
c-kzg = ["dep:c-kzg", "revm-primitives/c-kzg", "dep:tempfile", "alloy-eips/kzg"]
c-kzg = ["dep:c-kzg", "revm-primitives/c-kzg", "dep:tempfile", "alloy-eips/kzg", "alloy-consensus/kzg"]
optimism = [
"reth-chainspec/optimism",
"reth-ethereum-forks/optimism",
Expand Down
6 changes: 1 addition & 5 deletions crates/primitives/src/alloy_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,7 @@ impl TryFrom<WithOtherFields<alloy_rpc_types::Transaction>> for Transaction {
max_fee_per_gas: tx
.max_fee_per_gas
.ok_or(ConversionError::MissingMaxFeePerGas)?,
gas_limit: tx
.gas
.try_into()
.map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?,
placeholder: tx.to.map(drop),
gas_limit: tx.gas,
to: tx.to.unwrap_or_default(),
value: tx.value,
access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?,
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/transaction/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl FillTxEnv for TransactionSigned {
tx_env.authorization_list = None;
}
Transaction::Eip4844(tx) => {
tx_env.gas_limit = tx.gas_limit;
tx_env.gas_limit = tx.gas_limit as u64;
tx_env.gas_price = U256::from(tx.max_fee_per_gas);
tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas));
tx_env.transact_to = TxKind::Call(tx.to);
Expand Down
325 changes: 1 addition & 324 deletions crates/primitives/src/transaction/eip4844.rs

Large diffs are not rendered by default.

25 changes: 12 additions & 13 deletions crates/primitives/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,12 @@ impl Transaction {
}

/// Get the transaction's type
pub const fn tx_type(&self) -> TxType {
pub fn tx_type(&self) -> TxType {
match self {
Self::Legacy(_) => TxType::Legacy,
Self::Eip2930(access_list_tx) => access_list_tx.tx_type(),
Self::Eip1559(dynamic_fee_tx) => dynamic_fee_tx.tx_type(),
Self::Eip4844(blob_tx) => blob_tx.tx_type(),
Self::Eip4844(blob_tx) => blob_tx.tx_type().into(),
Self::Eip7702(set_code_tx) => set_code_tx.tx_type(),
#[cfg(feature = "optimism")]
Self::Deposit(deposit_tx) => deposit_tx.tx_type(),
Expand Down Expand Up @@ -297,8 +297,8 @@ impl Transaction {
Self::Legacy(TxLegacy { gas_limit, .. }) => *gas_limit as u64,
Self::Eip2930(TxEip2930 { gas_limit, .. }) |
Self::Eip1559(TxEip1559 { gas_limit, .. }) |
Self::Eip4844(TxEip4844 { gas_limit, .. }) |
Self::Eip7702(TxEip7702 { gas_limit, .. }) => *gas_limit,
Self::Eip4844(TxEip4844 { gas_limit, .. }) => *gas_limit as u64,
#[cfg(feature = "optimism")]
Self::Deposit(TxDeposit { gas_limit, .. }) => *gas_limit,
}
Expand Down Expand Up @@ -526,7 +526,9 @@ impl Transaction {
Self::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.encode_with_signature(signature, out, with_header)
}
Self::Eip4844(blob_tx) => blob_tx.encode_with_signature(signature, out, with_header),
Self::Eip4844(blob_tx) => {
blob_tx.encode_with_signature(&signature.to_alloy_signature(), out, with_header)
}
Self::Eip7702(set_code_tx) => {
set_code_tx.encode_with_signature(signature, out, with_header)
}
Expand All @@ -541,7 +543,7 @@ impl Transaction {
Self::Legacy(tx) => tx.gas_limit = gas_limit.into(),
Self::Eip2930(tx) => tx.gas_limit = gas_limit,
Self::Eip1559(tx) => tx.gas_limit = gas_limit,
Self::Eip4844(tx) => tx.gas_limit = gas_limit,
Self::Eip4844(tx) => tx.gas_limit = gas_limit as u128,
Self::Eip7702(tx) => tx.gas_limit = gas_limit,
#[cfg(feature = "optimism")]
Self::Deposit(tx) => tx.gas_limit = gas_limit,
Expand Down Expand Up @@ -1207,7 +1209,9 @@ impl TransactionSigned {
Transaction::Eip1559(dynamic_fee_tx) => {
dynamic_fee_tx.payload_len_with_signature(&self.signature)
}
Transaction::Eip4844(blob_tx) => blob_tx.payload_len_with_signature(&self.signature),
Transaction::Eip4844(blob_tx) => {
blob_tx.encoded_len_with_signature(&self.signature.to_alloy_signature(), true)
}
Transaction::Eip7702(set_code_tx) => {
set_code_tx.payload_len_with_signature(&self.signature)
}
Expand Down Expand Up @@ -1336,7 +1340,7 @@ impl TransactionSigned {
let transaction = match tx_type {
TxType::Eip2930 => Transaction::Eip2930(TxEip2930::decode_inner(data)?),
TxType::Eip1559 => Transaction::Eip1559(TxEip1559::decode_inner(data)?),
TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode_inner(data)?),
TxType::Eip4844 => Transaction::Eip4844(TxEip4844::decode(data)?),
TxType::Eip7702 => Transaction::Eip7702(TxEip7702::decode_inner(data)?),
#[cfg(feature = "optimism")]
TxType::Deposit => Transaction::Deposit(TxDeposit::decode_inner(data)?),
Expand Down Expand Up @@ -1414,7 +1418,7 @@ impl TransactionSigned {
dynamic_fee_tx.payload_len_with_signature_without_header(&self.signature)
}
Transaction::Eip4844(blob_tx) => {
blob_tx.payload_len_with_signature_without_header(&self.signature)
blob_tx.encoded_len_with_signature(&self.signature.to_alloy_signature(), false)
}
Transaction::Eip7702(set_code_tx) => {
set_code_tx.payload_len_with_signature_without_header(&self.signature)
Expand Down Expand Up @@ -1519,11 +1523,6 @@ impl<'a> arbitrary::Arbitrary<'a> for TransactionSigned {
transaction.set_chain_id(chain_id % (u64::MAX / 2 - 36));
}

if let Transaction::Eip4844(ref mut tx_eip_4844) = transaction {
tx_eip_4844.placeholder =
if tx_eip_4844.to == Address::default() { None } else { Some(()) };
}

#[cfg(feature = "optimism")]
// Both `Some(0)` and `None` values are encoded as empty string byte. This introduces
// ambiguity in roundtrip tests. Patch the mint value of deposit transaction here, so that
Expand Down
6 changes: 3 additions & 3 deletions crates/primitives/src/transaction/sidecar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ impl BlobTransaction {

// Encode the inner tx list header, then its fields
tx_header.encode(out);
self.transaction.encode_fields(out);
self.transaction.encode_with_signature_fields(&self.signature.to_alloy_signature(), out);
tcoratger marked this conversation as resolved.
Show resolved Hide resolved

// Encode the signature
self.signature.encode(out);
Expand Down Expand Up @@ -234,7 +234,7 @@ impl BlobTransaction {
let inner_remaining_len = data.len();

// inner transaction
let transaction = TxEip4844::decode_inner(data)?;
let transaction = TxEip4844::decode(data)?;

// signature
let signature = Signature::decode(data)?;
Expand Down Expand Up @@ -265,7 +265,7 @@ impl BlobTransaction {
// Instead, we use `encode_with_signature`, which RLP encodes the transaction with a
// signature for hashing without a header. We then hash the result.
let mut buf = Vec::new();
transaction.encode_with_signature(&signature, &mut buf, false);
transaction.encode_with_signature(&signature.to_alloy_signature(), &mut buf, false);
let hash = keccak256(&buf);

// the outer header is for the entire transaction, so we check the length here
Expand Down
10 changes: 10 additions & 0 deletions crates/primitives/src/transaction/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ impl Signature {
core::mem::size_of::<Self>()
}

/// Converts the signature to an alloy signature.
pub fn to_alloy_signature(&self) -> alloy_primitives::Signature {
alloy_primitives::Signature::from_rs_and_parity(
self.r,
self.s,
alloy_primitives::Parity::Parity(self.odd_y_parity),
)
.expect("failed to create alloy signature")
}

/// Returns [Parity] value based on `chain_id` for legacy transaction signature.
#[allow(clippy::missing_const_for_fn)]
pub fn legacy_parity(&self, chain_id: Option<u64>) -> Parity {
Expand Down
1 change: 0 additions & 1 deletion crates/rpc/rpc-types-compat/src/transaction/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ pub fn to_primitive_transaction(
gas_limit: tx.gas_limit.to(),
max_fee_per_gas: tx.max_fee_per_gas.to(),
max_priority_fee_per_gas: tx.max_priority_fee_per_gas.to(),
placeholder: Some(()),
to: tx.to,
value: tx.value,
access_list: tx.access_list,
Expand Down
2 changes: 1 addition & 1 deletion crates/storage/codecs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ workspace = true
reth-codecs-derive = { path = "./derive", default-features = false }

# eth
alloy-consensus = { workspace = true, optional = true }
alloy-consensus = { workspace = true, optional = true, features = ["serde"] }
alloy-eips = { workspace = true, optional = true }
alloy-genesis = { workspace = true, optional = true }
alloy-primitives.workspace = true
Expand Down
128 changes: 128 additions & 0 deletions crates/storage/codecs/src/alloy/eip4844.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use crate::{Compact, CompactPlaceholder};
use alloy_consensus::transaction::TxEip4844 as AlloyTxEip4844;
use alloy_eips::eip2930::AccessList;
use alloy_primitives::{Address, Bytes, ChainId, B256, U256};
use reth_codecs_derive::add_arbitrary_tests;
use serde::{Deserialize, Serialize};

/// [EIP-4844 Blob Transaction](https://eips.ethereum.org/EIPS/eip-4844#blob-transaction)
///
/// A transaction with blob hashes and max blob fee
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize, Compact)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
#[add_arbitrary_tests(compact)]
struct TxEip4844 {
tcoratger marked this conversation as resolved.
Show resolved Hide resolved
/// Added as EIP-155: Simple replay attack protection
pub chain_id: ChainId,

/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
pub nonce: u64,

/// A scalar value equal to the maximum
/// amount of gas that should be used in executing
/// this transaction. This is paid up-front, before any
/// computation is done and may not be increased
/// later; formally Tg.
pub gas_limit: u64,

/// A scalar value equal to the maximum
/// amount of gas that should be used in executing
/// this transaction. This is paid up-front, before any
/// computation is done and may not be increased
/// later; formally Tg.
///
/// As ethereum circulation is around 120mil eth as of 2022 that is around
/// 120000000000000000000000000 wei we are safe to use u128 as its max number is:
/// 340282366920938463463374607431768211455
///
/// This is also known as `GasFeeCap`
pub max_fee_per_gas: u128,

/// Max Priority fee that transaction is paying
///
/// As ethereum circulation is around 120mil eth as of 2022 that is around
/// 120000000000000000000000000 wei we are safe to use u128 as its max number is:
/// 340282366920938463463374607431768211455
///
/// This is also known as `GasTipCap`
pub max_priority_fee_per_gas: u128,

/// TODO(debt): this should be removed if we break the DB.
/// Makes sure that the Compact bitflag struct has one bit after the above field:
/// <https://github.com/paradigmxyz/reth/pull/8291#issuecomment-2117545016>
pub placeholder: Option<CompactPlaceholder>,

/// The 160-bit address of the message call’s recipient.
pub to: Address,

/// A scalar value equal to the number of Wei to
/// be transferred to the message call’s recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
pub value: U256,

/// The accessList specifies a list of addresses and storage keys;
/// these addresses and storage keys are added into the `accessed_addresses`
/// and `accessed_storage_keys` global sets (introduced in EIP-2929).
/// A gas cost is charged, though at a discount relative to the cost of
/// accessing outside the list.
pub access_list: AccessList,

/// It contains a vector of fixed size hash(32 bytes)
pub blob_versioned_hashes: Vec<B256>,

/// Max fee per data gas
///
/// aka BlobFeeCap or blobGasFeeCap
pub max_fee_per_blob_gas: u128,

/// Unlike other transaction types, where the `input` field has two uses depending on whether
/// or not the `to` field is [`Create`](crate::TxKind::Create) or
/// [`Call`](crate::TxKind::Call), EIP-4844 transactions cannot be
/// [`Create`](crate::TxKind::Create) transactions.
///
/// This means the `input` field has a single use, as data: An unlimited size byte array
/// specifying the input data of the message call, formally Td.
pub input: Bytes,
}
tcoratger marked this conversation as resolved.
Show resolved Hide resolved

impl Compact for AlloyTxEip4844 {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
let tx = TxEip4844 {
chain_id: self.chain_id,
nonce: self.nonce,
gas_limit: self.gas_limit as u64,
max_fee_per_gas: self.max_fee_per_gas,
max_priority_fee_per_gas: self.max_priority_fee_per_gas,
placeholder: None,
to: self.to,
value: self.value,
access_list: self.access_list.clone(),
blob_versioned_hashes: self.blob_versioned_hashes.clone(),
max_fee_per_blob_gas: self.max_fee_per_blob_gas,
input: self.input.clone(),
};
tx.to_compact(buf)
}

fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
let (tx, _) = TxEip4844::from_compact(buf, len);
let alloy_tx = Self {
chain_id: tx.chain_id,
nonce: tx.nonce,
gas_limit: tx.gas_limit as u128,
max_fee_per_gas: tx.max_fee_per_gas,
max_priority_fee_per_gas: tx.max_priority_fee_per_gas,
to: tx.to,
value: tx.value,
access_list: tx.access_list,
blob_versioned_hashes: tx.blob_versioned_hashes,
max_fee_per_blob_gas: tx.max_fee_per_blob_gas,
input: tx.input,
};
(alloy_tx, buf)
}
}
1 change: 1 addition & 0 deletions crates/storage/codecs/src/alloy/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod access_list;
mod authorization_list;
mod eip4844;
mod genesis_account;
mod log;
mod request;
Expand Down
5 changes: 1 addition & 4 deletions crates/storage/db-api/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,7 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion));
mod tests {
use super::*;
use reth_primitives::{
Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip1559, TxEip2930, TxEip4844,
Withdrawals,
Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip1559, TxEip2930, Withdrawals,
};
use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment};
use reth_stages_types::{
Expand Down Expand Up @@ -345,7 +344,6 @@ mod tests {
assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4);
assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3);
assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5);
assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0);
}

Expand Down Expand Up @@ -377,7 +375,6 @@ mod tests {
assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
assert_eq!(TxEip1559::bitflag_encoded_bytes(), 4);
assert_eq!(TxEip2930::bitflag_encoded_bytes(), 3);
assert_eq!(TxEip4844::bitflag_encoded_bytes(), 5);
assert_eq!(Withdrawals::bitflag_encoded_bytes(), 0);
}
}
3 changes: 1 addition & 2 deletions crates/transaction-pool/src/test_utils/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,9 @@ impl TransactionBuilder {
TxEip4844 {
chain_id: self.chain_id,
nonce: self.nonce,
gas_limit: self.gas_limit,
gas_limit: self.gas_limit as u128,
max_fee_per_gas: self.max_fee_per_gas,
max_priority_fee_per_gas: self.max_priority_fee_per_gas,
placeholder: None,
to: match self.to {
TxKind::Call(to) => to,
TxKind::Create => Address::default(),
Expand Down
Loading
Loading