fix: prevent CREATE tx for EIP-4844 types (#8291)

Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
This commit is contained in:
Federico Gimenez
2024-05-21 10:45:23 +02:00
committed by GitHub
parent adbe1ba9b1
commit 5100ddd28e
15 changed files with 120 additions and 39 deletions

View File

@ -182,7 +182,8 @@ impl TryFrom<alloy_rpc_types::Transaction> for Transaction {
.gas
.try_into()
.map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?,
to: tx.to.map_or(TxKind::Create, TxKind::Call),
placeholder: tx.to.map(|_| ()),
to: tx.to.unwrap_or_default(),
value: tx.value,
access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?,
input: tx.input,

View File

@ -272,10 +272,7 @@ where
tx_env.gas_limit = tx.gas_limit;
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 = match tx.to {
TxKind::Call(to) => TransactTo::Call(to),
TxKind::Create => TransactTo::create(),
};
tx_env.transact_to = TransactTo::Call(tx.to);
tx_env.value = tx.value;
tx_env.data = tx.input.clone();
tx_env.chain_id = Some(tx.chain_id);

View File

@ -1,10 +1,10 @@
use super::access_list::AccessList;
use crate::{
constants::eip4844::DATA_GAS_PER_BLOB, keccak256, Bytes, ChainId, Signature, TxKind, TxType,
constants::eip4844::DATA_GAS_PER_BLOB, keccak256, Address, Bytes, ChainId, Signature, TxType,
B256, U256,
};
use alloy_rlp::{length_of_length, Decodable, Encodable, Header};
use reth_codecs::{main_codec, Compact};
use reth_codecs::{main_codec, Compact, CompactPlaceholder};
use std::mem;
#[cfg(feature = "c-kzg")]
@ -46,9 +46,12 @@ pub struct TxEip4844 {
///
/// This is also known as `GasTipCap`
pub max_priority_fee_per_gas: u128,
/// The 160-bit address of the message calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
pub to: TxKind,
/// 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 calls recipient.
pub to: Address,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
@ -148,6 +151,7 @@ impl TxEip4844 {
max_priority_fee_per_gas: Decodable::decode(buf)?,
max_fee_per_gas: Decodable::decode(buf)?,
gas_limit: Decodable::decode(buf)?,
placeholder: Some(()),
to: Decodable::decode(buf)?,
value: Decodable::decode(buf)?,
input: Decodable::decode(buf)?,
@ -195,7 +199,7 @@ impl TxEip4844 {
mem::size_of::<u64>() + // gas_limit
mem::size_of::<u128>() + // max_fee_per_gas
mem::size_of::<u128>() + // max_priority_fee_per_gas
self.to.size() + // to
mem::size_of::<Address>() + // to
mem::size_of::<U256>() + // value
self.access_list.size() + // access_list
self.input.len() + // input
@ -272,3 +276,20 @@ impl TxEip4844 {
keccak256(&buf)
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{address, bytes};
#[test]
fn backwards_compatible_txkind_test() {
// TxEip4844 encoded with TxKind on to field
// holesky tx hash: <0xa3b1668225bf0fbfdd6c19aa6fd071fa4ff5d09a607c67ccd458b97735f745ac>
let tx = bytes!("224348a100426844cb2dc6c0b2d05e003b9aca0079c9109b764609df928d16fc4a91e9081f7e87db09310001019101fb28118ceccaabca22a47e35b9c3f12eb2dcb25e5c543d5b75e6cd841f0a05328d26ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007b399987d24fc5951f3e94a4cb16e87414bf22290000000000000000000000001670090000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000009e640a6aadf4f664cf467b795c31332f44acbe6c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006614c2d1000000000000000000000000000000000000000000000000000000000014012c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f06fd78f4dcdf089263524731620941747b9b93fd8f631557e25b23845a78b685bd82f9d36bce2f4cc812b6e5191df52479d349089461ffe76e9f2fa2848a0fe1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410819f04aba17677807c61ae72afdddf7737f26931ecfa8af05b7c669808b36a2587e32c90bb0ed2100266dd7797c80121a109a2b0fe941ca5a580e438988cac81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
let (tx, _) = TxEip4844::from_compact(&tx, tx.len());
assert_eq!(tx.to, address!("79C9109b764609df928d16fC4a91e9081F7e87DB"));
assert_eq!(tx.placeholder, Some(()));
assert_eq!(tx.input, bytes!("ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007b399987d24fc5951f3e94a4cb16e87414bf22290000000000000000000000001670090000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000009e640a6aadf4f664cf467b795c31332f44acbe6c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006614c2d1000000000000000000000000000000000000000000000000000000000014012c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000093100000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f06fd78f4dcdf089263524731620941747b9b93fd8f631557e25b23845a78b685bd82f9d36bce2f4cc812b6e5191df52479d349089461ffe76e9f2fa2848a0fe1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410819f04aba17677807c61ae72afdddf7737f26931ecfa8af05b7c669808b36a2587e32c90bb0ed2100266dd7797c80121a109a2b0fe941ca5a580e438988cac81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
}
}

View File

@ -77,7 +77,7 @@ pub const MIN_LENGTH_EIP2930_TX_ENCODED: usize = 14;
/// Minimum length of a rlp-encoded eip1559 transaction.
pub const MIN_LENGTH_EIP1559_TX_ENCODED: usize = 15;
/// Minimum length of a rlp-encoded eip4844 transaction.
pub const MIN_LENGTH_EIP4844_TX_ENCODED: usize = 17;
pub const MIN_LENGTH_EIP4844_TX_ENCODED: usize = 37;
/// Minimum length of a rlp-encoded deposit transaction.
#[cfg(feature = "optimism")]
pub const MIN_LENGTH_DEPOSIT_TX_ENCODED: usize = 65;
@ -174,14 +174,14 @@ impl Transaction {
/// Gets the transaction's [`TxKind`], which is the address of the recipient or
/// [`TxKind::Create`] if the transaction is a contract creation.
pub fn kind(&self) -> &TxKind {
pub fn kind(&self) -> TxKind {
match self {
Transaction::Legacy(TxLegacy { to, .. }) |
Transaction::Eip2930(TxEip2930 { to, .. }) |
Transaction::Eip1559(TxEip1559 { to, .. }) |
Transaction::Eip4844(TxEip4844 { to, .. }) => to,
Transaction::Eip1559(TxEip1559 { to, .. }) => *to,
Transaction::Eip4844(TxEip4844 { to, .. }) => TxKind::Call(*to),
#[cfg(feature = "optimism")]
Transaction::Deposit(TxDeposit { to, .. }) => to,
Transaction::Deposit(TxDeposit { to, .. }) => *to,
}
}
@ -1462,6 +1462,11 @@ impl proptest::arbitrary::Arbitrary for TransactionSigned {
.then(Signature::optimism_deposit_tx_signature)
.unwrap_or(sig);
if let Transaction::Eip4844(ref mut tx_eip_4844) = transaction {
tx_eip_4844.placeholder =
if tx_eip_4844.to != Address::default() { Some(()) } else { None };
}
let mut tx =
TransactionSigned { hash: Default::default(), signature: sig, transaction };
tx.hash = tx.recalculate_hash();
@ -2035,7 +2040,10 @@ mod tests {
);
let encoded = alloy_rlp::encode(signed_tx);
assert_eq!(hex!("9003ce8080808080808080c080c0808080"), encoded[..]);
assert_eq!(
hex!("a403e280808080809400000000000000000000000000000000000000008080c080c0808080"),
encoded[..]
);
assert_eq!(MIN_LENGTH_EIP4844_TX_ENCODED, encoded.len());
TransactionSigned::decode(&mut &encoded[..]).unwrap();
@ -2150,4 +2158,13 @@ mod tests {
let written_bytes = tx_signed_no_hash.to_compact(&mut buff);
from_compact_zstd_unaware(&buff, written_bytes);
}
#[test]
fn create_txs_disallowed_for_eip4844() {
let data =
[3, 208, 128, 128, 123, 128, 120, 128, 129, 129, 128, 192, 129, 129, 192, 128, 128, 9];
let res = TransactionSigned::decode_enveloped(&mut &data[..]);
assert!(res.is_err());
}
}