feat(eip4844): include TxEip4844 in the primitive Transaction enum (#4074)

This commit is contained in:
Thomas Coratger
2023-08-07 21:10:12 +02:00
committed by GitHub
parent 310179a39a
commit c1dfa7beba
6 changed files with 275 additions and 15 deletions

View File

@@ -7,7 +7,7 @@ use reth_primitives::{
eip4844::{DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK},
},
BlockNumber, ChainSpec, Hardfork, Header, InvalidTransactionError, SealedBlock, SealedHeader,
Transaction, TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxLegacy,
Transaction, TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxEip4844, TxLegacy,
};
use reth_provider::{AccountReader, HeaderProvider, WithdrawalsProvider};
use std::collections::{hash_map::Entry, HashMap};
@@ -98,6 +98,20 @@ pub fn validate_transaction_regarding_header(
return Err(InvalidTransactionError::TipAboveFeeCap.into())
}
Some(*chain_id)
}
Transaction::Eip4844(TxEip4844 {
chain_id,
max_fee_per_gas,
max_priority_fee_per_gas,
..
}) => {
// EIP-1559: add more constraints to the tx validation
// https://github.com/ethereum/EIPs/pull/3594
if max_priority_fee_per_gas > max_fee_per_gas {
return Err(InvalidTransactionError::TipAboveFeeCap.into())
}
Some(*chain_id)
}
};

View File

@@ -65,6 +65,18 @@ pub enum Transaction {
/// transaction, incentivizing miners to include transactions with higher priority fees per
/// gas.
Eip1559(TxEip1559),
/// Shard Blob Transactions ([EIP-4844](https://eips.ethereum.org/EIPS/eip-4844)), type `0x3`.
///
/// Shard Blob Transactions introduce a new transaction type called a blob-carrying transaction
/// to reduce gas costs. These transactions are similar to regular Ethereum transactions but
/// include additional data called a blob.
///
/// Blobs are larger (~125 kB) and cheaper than the current calldata, providing an immutable
/// and read-only memory for storing transaction data.
///
/// EIP-4844, also known as proto-danksharding, implements the framework and logic of
/// danksharding, introducing new transaction formats and verification rules.
Eip4844(TxEip4844),
}
impl Transaction {
@@ -116,6 +128,7 @@ impl Transaction {
Transaction::Legacy(tx) => tx.nonce = nonce,
Transaction::Eip2930(tx) => tx.nonce = nonce,
Transaction::Eip1559(tx) => tx.nonce = nonce,
Transaction::Eip4844(tx) => tx.nonce = nonce,
}
}
@@ -125,6 +138,7 @@ impl Transaction {
Transaction::Legacy(tx) => tx.value = value,
Transaction::Eip2930(tx) => tx.value = value,
Transaction::Eip1559(tx) => tx.value = value,
Transaction::Eip4844(tx) => tx.value = value,
}
}
@@ -134,6 +148,7 @@ impl Transaction {
Transaction::Legacy(tx) => tx.input = input,
Transaction::Eip2930(tx) => tx.input = input,
Transaction::Eip1559(tx) => tx.input = input,
Transaction::Eip4844(tx) => tx.input = input,
}
}
@@ -144,6 +159,7 @@ impl Transaction {
Transaction::Legacy(tx) => tx.size(),
Transaction::Eip2930(tx) => tx.size(),
Transaction::Eip1559(tx) => tx.size(),
Transaction::Eip4844(tx) => tx.size(),
}
}
}
@@ -166,6 +182,10 @@ impl Compact for Transaction {
tx.to_compact(buf);
2
}
Transaction::Eip4844(tx) => {
tx.to_compact(buf);
3
}
}
}
@@ -183,6 +203,10 @@ impl Compact for Transaction {
let (tx, buf) = TxEip1559::from_compact(buf, buf.len());
(Transaction::Eip1559(tx), buf)
}
3 => {
let (tx, buf) = TxEip4844::from_compact(buf, buf.len());
(Transaction::Eip4844(tx), buf)
}
_ => unreachable!("Junk data in database: unknown Transaction variant"),
}
}
@@ -205,6 +229,7 @@ impl Transaction {
Transaction::Legacy(TxLegacy { chain_id, .. }) => *chain_id,
Transaction::Eip2930(TxEip2930 { chain_id, .. }) => Some(*chain_id),
Transaction::Eip1559(TxEip1559 { chain_id, .. }) => Some(*chain_id),
Transaction::Eip4844(TxEip4844 { chain_id, .. }) => Some(*chain_id),
}
}
@@ -214,6 +239,7 @@ impl Transaction {
Transaction::Legacy(TxLegacy { chain_id: ref mut c, .. }) => *c = Some(chain_id),
Transaction::Eip2930(TxEip2930 { chain_id: ref mut c, .. }) => *c = chain_id,
Transaction::Eip1559(TxEip1559 { chain_id: ref mut c, .. }) => *c = chain_id,
Transaction::Eip4844(TxEip4844 { chain_id: ref mut c, .. }) => *c = chain_id,
}
}
@@ -223,7 +249,8 @@ impl Transaction {
match self {
Transaction::Legacy(TxLegacy { to, .. }) |
Transaction::Eip2930(TxEip2930 { to, .. }) |
Transaction::Eip1559(TxEip1559 { to, .. }) => to,
Transaction::Eip1559(TxEip1559 { to, .. }) |
Transaction::Eip4844(TxEip4844 { to, .. }) => to,
}
}
@@ -238,6 +265,7 @@ impl Transaction {
Transaction::Legacy { .. } => TxType::Legacy,
Transaction::Eip2930 { .. } => TxType::EIP2930,
Transaction::Eip1559 { .. } => TxType::EIP1559,
Transaction::Eip4844 { .. } => TxType::EIP4844,
}
}
@@ -247,6 +275,7 @@ impl Transaction {
Transaction::Legacy(TxLegacy { value, .. }) => value,
Transaction::Eip2930(TxEip2930 { value, .. }) => value,
Transaction::Eip1559(TxEip1559 { value, .. }) => value,
Transaction::Eip4844(TxEip4844 { value, .. }) => value,
}
}
@@ -256,6 +285,7 @@ impl Transaction {
Transaction::Legacy(TxLegacy { nonce, .. }) => *nonce,
Transaction::Eip2930(TxEip2930 { nonce, .. }) => *nonce,
Transaction::Eip1559(TxEip1559 { nonce, .. }) => *nonce,
Transaction::Eip4844(TxEip4844 { nonce, .. }) => *nonce,
}
}
@@ -264,7 +294,8 @@ impl Transaction {
match self {
Transaction::Legacy(TxLegacy { gas_limit, .. }) |
Transaction::Eip2930(TxEip2930 { gas_limit, .. }) |
Transaction::Eip1559(TxEip1559 { gas_limit, .. }) => *gas_limit,
Transaction::Eip1559(TxEip1559 { gas_limit, .. }) |
Transaction::Eip4844(TxEip4844 { gas_limit, .. }) => *gas_limit,
}
}
@@ -275,7 +306,8 @@ impl Transaction {
match self {
Transaction::Legacy(TxLegacy { gas_price, .. }) |
Transaction::Eip2930(TxEip2930 { gas_price, .. }) => *gas_price,
Transaction::Eip1559(TxEip1559 { max_fee_per_gas, .. }) => *max_fee_per_gas,
Transaction::Eip1559(TxEip1559 { max_fee_per_gas, .. }) |
Transaction::Eip4844(TxEip4844 { max_fee_per_gas, .. }) => *max_fee_per_gas,
}
}
@@ -287,7 +319,8 @@ impl Transaction {
match self {
Transaction::Legacy(_) => None,
Transaction::Eip2930(_) => None,
Transaction::Eip1559(TxEip1559 { max_priority_fee_per_gas, .. }) => {
Transaction::Eip1559(TxEip1559 { max_priority_fee_per_gas, .. }) |
Transaction::Eip4844(TxEip4844 { max_priority_fee_per_gas, .. }) => {
Some(*max_priority_fee_per_gas)
}
}
@@ -304,7 +337,8 @@ impl Transaction {
match self {
Transaction::Legacy(TxLegacy { gas_price, .. }) |
Transaction::Eip2930(TxEip2930 { gas_price, .. }) => *gas_price,
Transaction::Eip1559(TxEip1559 { max_priority_fee_per_gas, .. }) => {
Transaction::Eip1559(TxEip1559 { max_priority_fee_per_gas, .. }) |
Transaction::Eip4844(TxEip4844 { max_priority_fee_per_gas, .. }) => {
*max_priority_fee_per_gas
}
}
@@ -318,6 +352,7 @@ impl Transaction {
Transaction::Legacy(tx) => tx.gas_price,
Transaction::Eip2930(tx) => tx.gas_price,
Transaction::Eip1559(dynamic_tx) => dynamic_tx.effective_gas_price(base_fee),
Transaction::Eip4844(dynamic_tx) => dynamic_tx.effective_gas_price(base_fee),
}
}
@@ -373,6 +408,7 @@ impl Transaction {
Transaction::Legacy(TxLegacy { input, .. }) => input,
Transaction::Eip2930(TxEip2930 { input, .. }) => input,
Transaction::Eip1559(TxEip1559 { input, .. }) => input,
Transaction::Eip4844(TxEip4844 { input, .. }) => input,
}
}
@@ -469,6 +505,33 @@ impl Transaction {
len += access_list.length();
len
}
Transaction::Eip4844(TxEip4844 {
chain_id,
nonce,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
to,
value,
access_list,
blob_versioned_hashes,
max_fee_per_blob_gas,
input,
}) => {
let mut len = 0;
len += chain_id.length();
len += nonce.length();
len += gas_limit.length();
len += max_fee_per_gas.length();
len += max_priority_fee_per_gas.length();
len += to.length();
len += value.length();
len += access_list.length();
len += blob_versioned_hashes.length();
len += max_fee_per_blob_gas.length();
len += input.0.length();
len
}
}
}
@@ -531,6 +594,31 @@ impl Transaction {
input.0.encode(out);
access_list.encode(out);
}
Transaction::Eip4844(TxEip4844 {
chain_id,
nonce,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
to,
value,
access_list,
blob_versioned_hashes,
max_fee_per_blob_gas,
input,
}) => {
chain_id.encode(out);
nonce.encode(out);
max_priority_fee_per_gas.encode(out);
max_fee_per_gas.encode(out);
gas_limit.encode(out);
to.encode(out);
value.encode(out);
input.0.encode(out);
access_list.encode(out);
max_fee_per_blob_gas.encode(out);
blob_versioned_hashes.encode(out);
}
}
}
}
@@ -1012,6 +1100,19 @@ impl TransactionSigned {
input: Bytes(Decodable::decode(data)?),
access_list: Decodable::decode(data)?,
}),
3 => Transaction::Eip4844(TxEip4844 {
chain_id: Decodable::decode(data)?,
nonce: Decodable::decode(data)?,
max_priority_fee_per_gas: Decodable::decode(data)?,
max_fee_per_gas: Decodable::decode(data)?,
gas_limit: Decodable::decode(data)?,
to: Decodable::decode(data)?,
value: Decodable::decode(data)?,
input: Bytes(Decodable::decode(data)?),
access_list: Decodable::decode(data)?,
max_fee_per_blob_gas: Decodable::decode(data)?,
blob_versioned_hashes: Decodable::decode(data)?,
}),
_ => return Err(DecodeError::Custom("unsupported typed transaction type")),
};

View File

@@ -1,7 +1,7 @@
use crate::config::revm_spec;
use reth_primitives::{
recover_signer, Address, Bytes, Chain, ChainSpec, Head, Header, Transaction, TransactionKind,
TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxLegacy, U256,
TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxEip4844, TxLegacy, U256,
};
use revm::primitives::{AnalysisKind, BlockEnv, CfgEnv, SpecId, TransactTo, TxEnv};
@@ -212,5 +212,43 @@ where
})
.collect();
}
Transaction::Eip4844(TxEip4844 {
nonce,
chain_id,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
to,
value,
access_list,
blob_versioned_hashes: _,
max_fee_per_blob_gas: _,
input,
}) => {
tx_env.gas_limit = *gas_limit;
tx_env.gas_price = U256::from(*max_fee_per_gas);
tx_env.gas_priority_fee = Some(U256::from(*max_priority_fee_per_gas));
tx_env.transact_to = match to {
TransactionKind::Call(to) => TransactTo::Call(*to),
TransactionKind::Create => TransactTo::create(),
};
tx_env.value = U256::from(*value);
tx_env.data = input.0.clone();
tx_env.chain_id = Some(*chain_id);
tx_env.nonce = Some(*nonce);
tx_env.access_list = access_list
.0
.iter()
.map(|l| {
(
l.address,
l.storage_keys
.iter()
.map(|k| U256::from_be_bytes(k.to_fixed_bytes()))
.collect(),
)
})
.collect();
}
}
}

View File

@@ -148,6 +148,16 @@ impl Transaction {
})
.collect(),
),
PrimitiveTransaction::Eip4844(tx) => Some(
tx.access_list
.0
.iter()
.map(|item| AccessListItem {
address: item.address.0.into(),
storage_keys: item.storage_keys.iter().map(|key| key.0.into()).collect(),
})
.collect(),
),
};
let signature = Signature::from_primitive_signature(

View File

@@ -14,7 +14,8 @@ use rand::{
use reth_primitives::{
constants::MIN_PROTOCOL_BASE_FEE, hex, Address, FromRecoveredTransaction,
IntoRecoveredTransaction, Signature, Transaction, TransactionKind, TransactionSigned,
TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxHash, TxLegacy, TxType, H256, U128, U256,
TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxEip4844, TxHash, TxLegacy, TxType, H256,
U128, U256,
};
use std::{ops::Range, sync::Arc, time::Instant};
@@ -38,6 +39,9 @@ macro_rules! set_value {
MockTransaction::Eip1559 { ref mut $field, .. } => {
*$field = new_value;
}
MockTransaction::Eip4844 { ref mut $field, .. } => {
*$field = new_value;
}
}
};
}
@@ -48,6 +52,7 @@ macro_rules! get_value {
match $this {
MockTransaction::Legacy { $field, .. } => $field,
MockTransaction::Eip1559 { $field, .. } => $field,
MockTransaction::Eip4844 { $field, .. } => $field,
}
};
}
@@ -99,6 +104,16 @@ pub enum MockTransaction {
to: TransactionKind,
value: U256,
},
Eip4844 {
hash: H256,
sender: Address,
nonce: u64,
max_fee_per_gas: u128,
max_priority_fee_per_gas: u128,
gas_limit: u64,
to: TransactionKind,
value: U256,
},
}
// === impl MockTransaction ===
@@ -140,21 +155,27 @@ impl MockTransaction {
}
pub fn set_priority_fee(&mut self, val: u128) -> &mut Self {
if let MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } = self {
if let (MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } |
MockTransaction::Eip4844 { max_priority_fee_per_gas, .. }) = self
{
*max_priority_fee_per_gas = val;
}
self
}
pub fn with_priority_fee(mut self, val: u128) -> Self {
if let MockTransaction::Eip1559 { ref mut max_priority_fee_per_gas, .. } = self {
if let (MockTransaction::Eip1559 { ref mut max_priority_fee_per_gas, .. } |
MockTransaction::Eip4844 { ref mut max_priority_fee_per_gas, .. }) = self
{
*max_priority_fee_per_gas = val;
}
self
}
pub fn get_priority_fee(&self) -> Option<u128> {
if let MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } = self {
if let (MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } |
MockTransaction::Eip4844 { max_priority_fee_per_gas, .. }) = self
{
Some(*max_priority_fee_per_gas)
} else {
None
@@ -162,21 +183,27 @@ impl MockTransaction {
}
pub fn set_max_fee(&mut self, val: u128) -> &mut Self {
if let MockTransaction::Eip1559 { max_fee_per_gas, .. } = self {
if let (MockTransaction::Eip1559 { max_fee_per_gas, .. } |
MockTransaction::Eip4844 { max_fee_per_gas, .. }) = self
{
*max_fee_per_gas = val;
}
self
}
pub fn with_max_fee(mut self, val: u128) -> Self {
if let MockTransaction::Eip1559 { ref mut max_fee_per_gas, .. } = self {
if let (MockTransaction::Eip1559 { ref mut max_fee_per_gas, .. } |
MockTransaction::Eip4844 { ref mut max_fee_per_gas, .. }) = self
{
*max_fee_per_gas = val;
}
self
}
pub fn get_max_fee(&self) -> Option<u128> {
if let MockTransaction::Eip1559 { max_fee_per_gas, .. } = self {
if let (MockTransaction::Eip1559 { max_fee_per_gas, .. } |
MockTransaction::Eip4844 { max_fee_per_gas, .. }) = self
{
Some(*max_fee_per_gas)
} else {
None
@@ -192,6 +219,10 @@ impl MockTransaction {
*max_fee_per_gas = val;
*max_priority_fee_per_gas = val;
}
MockTransaction::Eip4844 { max_fee_per_gas, max_priority_fee_per_gas, .. } => {
*max_fee_per_gas = val;
*max_priority_fee_per_gas = val;
}
}
self
}
@@ -209,6 +240,14 @@ impl MockTransaction {
*max_fee_per_gas = val;
*max_priority_fee_per_gas = val;
}
MockTransaction::Eip4844 {
ref mut max_fee_per_gas,
ref mut max_priority_fee_per_gas,
..
} => {
*max_fee_per_gas = val;
*max_priority_fee_per_gas = val;
}
}
self
}
@@ -217,6 +256,7 @@ impl MockTransaction {
match self {
MockTransaction::Legacy { gas_price, .. } => *gas_price,
MockTransaction::Eip1559 { max_fee_per_gas, .. } => *max_fee_per_gas,
MockTransaction::Eip4844 { max_fee_per_gas, .. } => *max_fee_per_gas,
}
}
@@ -301,6 +341,7 @@ impl PoolTransaction for MockTransaction {
match self {
MockTransaction::Legacy { hash, .. } => hash,
MockTransaction::Eip1559 { hash, .. } => hash,
MockTransaction::Eip4844 { hash, .. } => hash,
}
}
@@ -308,6 +349,7 @@ impl PoolTransaction for MockTransaction {
match self {
MockTransaction::Legacy { sender, .. } => *sender,
MockTransaction::Eip1559 { sender, .. } => *sender,
MockTransaction::Eip4844 { sender, .. } => *sender,
}
}
@@ -315,6 +357,7 @@ impl PoolTransaction for MockTransaction {
match self {
MockTransaction::Legacy { nonce, .. } => *nonce,
MockTransaction::Eip1559 { nonce, .. } => *nonce,
MockTransaction::Eip4844 { nonce, .. } => *nonce,
}
}
@@ -326,6 +369,9 @@ impl PoolTransaction for MockTransaction {
MockTransaction::Eip1559 { max_fee_per_gas, value, gas_limit, .. } => {
U256::from(*gas_limit) * U256::from(*max_fee_per_gas) + *value
}
MockTransaction::Eip4844 { max_fee_per_gas, value, gas_limit, .. } => {
U256::from(*gas_limit) * U256::from(*max_fee_per_gas) + *value
}
}
}
@@ -337,6 +383,7 @@ impl PoolTransaction for MockTransaction {
match self {
MockTransaction::Legacy { gas_price, .. } => *gas_price,
MockTransaction::Eip1559 { max_fee_per_gas, .. } => *max_fee_per_gas,
MockTransaction::Eip4844 { max_fee_per_gas, .. } => *max_fee_per_gas,
}
}
@@ -346,6 +393,9 @@ impl PoolTransaction for MockTransaction {
MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } => {
Some(*max_priority_fee_per_gas)
}
MockTransaction::Eip4844 { max_priority_fee_per_gas, .. } => {
Some(*max_priority_fee_per_gas)
}
}
}
@@ -368,6 +418,7 @@ impl PoolTransaction for MockTransaction {
match self {
MockTransaction::Legacy { gas_price, .. } => *gas_price,
MockTransaction::Eip1559 { max_priority_fee_per_gas, .. } => *max_priority_fee_per_gas,
MockTransaction::Eip4844 { max_priority_fee_per_gas, .. } => *max_priority_fee_per_gas,
}
}
@@ -375,6 +426,7 @@ impl PoolTransaction for MockTransaction {
match self {
MockTransaction::Legacy { to, .. } => to,
MockTransaction::Eip1559 { to, .. } => to,
MockTransaction::Eip4844 { to, .. } => to,
}
}
@@ -386,6 +438,7 @@ impl PoolTransaction for MockTransaction {
match self {
MockTransaction::Legacy { .. } => TxType::Legacy.into(),
MockTransaction::Eip1559 { .. } => TxType::EIP1559.into(),
MockTransaction::Eip4844 { .. } => TxType::EIP4844.into(),
}
}
@@ -441,6 +494,28 @@ impl FromRecoveredTransaction for MockTransaction {
to,
value: U256::from(value),
},
Transaction::Eip4844(TxEip4844 {
chain_id,
nonce,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
to,
value,
input,
access_list,
blob_versioned_hashes: _,
max_fee_per_blob_gas: _,
}) => MockTransaction::Eip4844 {
hash,
sender,
nonce,
max_fee_per_gas,
max_priority_fee_per_gas,
gas_limit,
to,
value: U256::from(value),
},
Transaction::Eip2930 { .. } => {
unimplemented!()
}
@@ -527,6 +602,25 @@ impl proptest::arbitrary::Arbitrary for MockTransaction {
to: *to,
value: U256::from(*value),
},
Transaction::Eip4844(TxEip4844 {
nonce,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
to,
value,
input,
..
}) => MockTransaction::Eip4844 {
sender,
hash: tx_hash,
nonce: *nonce,
max_fee_per_gas: *max_fee_per_gas,
max_priority_fee_per_gas: *max_priority_fee_per_gas,
gas_limit: *gas_limit,
to: *to,
value: U256::from(*value),
},
})
.boxed()
}

View File

@@ -407,7 +407,7 @@ pub enum TransactionOrigin {
/// Transaction is originated locally and is intended to remain private.
///
/// This type of transaction should not be propagated to the network. It's meant for
/// private usage within the local node only.
/// private usage within the local node only.
Private,
}
@@ -582,6 +582,7 @@ impl PooledTransaction {
Transaction::Legacy(t) => U256::from(t.gas_price) * U256::from(t.gas_limit),
Transaction::Eip2930(t) => U256::from(t.gas_price) * U256::from(t.gas_limit),
Transaction::Eip1559(t) => U256::from(t.max_fee_per_gas) * U256::from(t.gas_limit),
Transaction::Eip4844(t) => U256::from(t.max_fee_per_gas) * U256::from(t.gas_limit),
};
let cost = gas_cost + U256::from(transaction.value());
@@ -633,6 +634,7 @@ impl PoolTransaction for PooledTransaction {
Transaction::Legacy(tx) => tx.gas_price,
Transaction::Eip2930(tx) => tx.gas_price,
Transaction::Eip1559(tx) => tx.max_fee_per_gas,
Transaction::Eip4844(tx) => tx.max_fee_per_gas,
}
}
@@ -644,6 +646,7 @@ impl PoolTransaction for PooledTransaction {
Transaction::Legacy(_) => None,
Transaction::Eip2930(_) => None,
Transaction::Eip1559(tx) => Some(tx.max_priority_fee_per_gas),
Transaction::Eip4844(tx) => Some(tx.max_priority_fee_per_gas),
}
}