diff --git a/src/eth_provider/database/types/transaction.rs b/src/eth_provider/database/types/transaction.rs index 52261ce92..42f28c6bd 100644 --- a/src/eth_provider/database/types/transaction.rs +++ b/src/eth_provider/database/types/transaction.rs @@ -1,6 +1,6 @@ use reth_primitives::B256; #[cfg(any(test, feature = "arbitrary", feature = "testing"))] -use reth_primitives::{Address, TransactionSigned, U256}; +use reth_primitives::{Address, TransactionSigned, TxType, U256}; use reth_rpc_types::Transaction; use serde::{Deserialize, Serialize}; @@ -28,6 +28,8 @@ impl<'a> arbitrary::Arbitrary<'a> for StoredTransaction { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { let transaction = TransactionSigned::arbitrary(u)?; + let transaction_type = Into::::into(transaction.tx_type()) % 3; + Ok(StoredTransaction { tx: Transaction { hash: transaction.hash, @@ -40,8 +42,16 @@ impl<'a> arbitrary::Arbitrary<'a> for StoredTransaction { value: transaction.value(), gas_price: Some(u128::arbitrary(u)?), gas: u64::arbitrary(u)? as u128, - max_fee_per_gas: Some(transaction.max_fee_per_gas()), - max_priority_fee_per_gas: Some(transaction.max_priority_fee_per_gas().unwrap_or_default()), + max_fee_per_gas: if TryInto::::try_into(transaction_type).unwrap() == TxType::Legacy { + None + } else { + Some(transaction.max_fee_per_gas()) + }, + max_priority_fee_per_gas: if TryInto::::try_into(transaction_type).unwrap() == TxType::Legacy { + None + } else { + Some(transaction.max_priority_fee_per_gas().unwrap_or_default()) + }, max_fee_per_blob_gas: transaction.max_fee_per_blob_gas(), input: transaction.input().clone(), signature: Some(reth_rpc_types::Signature { @@ -63,7 +73,6 @@ impl<'a> arbitrary::Arbitrary<'a> for StoredTransaction { .collect(), ) }), - transaction_type: Some(Into::::into(transaction.tx_type()) % 3), other: Default::default(), }, diff --git a/src/eth_provider/provider.rs b/src/eth_provider/provider.rs index 4484f9927..94bdc56f5 100644 --- a/src/eth_provider/provider.rs +++ b/src/eth_provider/provider.rs @@ -1,5 +1,4 @@ use crate::eth_provider::starknet::kakarot_core::account_contract::BytecodeOutput; -use crate::models::block::rpc_to_primitive_header; use alloy_rlp::{Decodable, Encodable}; use async_trait::async_trait; use auto_impl::auto_impl; @@ -826,7 +825,9 @@ where // This is how reth computes the block size. // `https://github.com/paradigmxyz/reth/blob/v0.2.0-beta.5/crates/rpc/rpc-types-compat/src/block.rs#L66` - let size = rpc_to_primitive_header(header.clone())?.length(); + let size = reth_primitives::Header::try_from(header.clone()) + .map_err(|_| EthereumDataFormatError::PrimitiveError)? + .length(); Ok(Some( Block { header, diff --git a/src/eth_rpc/servers/debug_rpc.rs b/src/eth_rpc/servers/debug_rpc.rs index d73609205..7c1f6731f 100644 --- a/src/eth_rpc/servers/debug_rpc.rs +++ b/src/eth_rpc/servers/debug_rpc.rs @@ -2,14 +2,12 @@ use std::sync::Arc; use alloy_rlp::Encodable; use jsonrpsee::core::{async_trait, RpcResult as Result}; -use reth_primitives::{Bytes, Log, Receipt, ReceiptWithBloom, TransactionSigned, B256}; +use reth_primitives::{Block, Bytes, Header, Log, Receipt, ReceiptWithBloom, TransactionSigned, B256}; use reth_rpc_types::trace::geth::{GethDebugTracingOptions, TraceResult}; use reth_rpc_types::{BlockId, BlockNumberOrTag}; use crate::eth_provider::error::{EthApiError, EthereumDataFormatError, SignatureError}; use crate::eth_rpc::api::debug_api::DebugApiServer; -use crate::models::block::rpc_to_primitive_block; -use crate::models::block::rpc_to_primitive_header; use crate::tracing::builder::TracerBuilder; use crate::{eth_provider::provider::EthereumProvider, models::transaction::rpc_to_primitive_transaction}; @@ -34,7 +32,7 @@ impl DebugApiServer for DebugRpc

.eth_provider .header(&block_id) .await? - .map(rpc_to_primitive_header) + .map(Header::try_from) .transpose() .map_err(|_| EthApiError::EthereumDataFormat(EthereumDataFormatError::HeaderConversionError))? { @@ -52,7 +50,8 @@ impl DebugApiServer for DebugRpc

}; let mut raw_block = Vec::new(); if let Some(block) = block { - let block = rpc_to_primitive_block(block.inner).map_err(EthApiError::from)?; + let block = + Block::try_from(block.inner).map_err(|_| EthApiError::from(EthereumDataFormatError::PrimitiveError))?; block.encode(&mut raw_block); } Ok(raw_block.into()) diff --git a/src/models/block.rs b/src/models/block.rs index 888665bba..543d33ae7 100644 --- a/src/models/block.rs +++ b/src/models/block.rs @@ -1,7 +1,6 @@ -use super::transaction::rpc_to_primitive_transaction; use crate::eth_provider::constant::STARKNET_MODULUS; use crate::{eth_provider::error::EthereumDataFormatError, into_via_try_wrapper}; -use reth_primitives::{BlockId as EthereumBlockId, BlockNumberOrTag, TransactionSigned, Withdrawals, U256}; +use reth_primitives::{BlockId as EthereumBlockId, BlockNumberOrTag, U256}; use starknet::core::types::{BlockId as StarknetBlockId, BlockTag}; #[derive(Debug)] @@ -67,84 +66,14 @@ impl From for StarknetBlockId { } } -pub fn rpc_to_primitive_header( - header: reth_rpc_types::Header, -) -> Result { - Ok(reth_primitives::Header { - base_fee_per_gas: header - .base_fee_per_gas - .map(|base_fee_per_gas| base_fee_per_gas.try_into().map_err(|_| EthereumDataFormatError::PrimitiveError)) - .transpose()?, - beneficiary: header.miner, - blob_gas_used: header - .blob_gas_used - .map(|blob_gas_used| blob_gas_used.try_into().map_err(|_| EthereumDataFormatError::PrimitiveError)) - .transpose()?, - difficulty: header.difficulty, - excess_blob_gas: header - .excess_blob_gas - .map(|excess_blob_gas| excess_blob_gas.try_into().map_err(|_| EthereumDataFormatError::PrimitiveError)) - .transpose()?, - extra_data: header.extra_data, - gas_limit: header.gas_limit.try_into().map_err(|_| EthereumDataFormatError::PrimitiveError)?, - gas_used: header.gas_used.try_into().map_err(|_| EthereumDataFormatError::PrimitiveError)?, - logs_bloom: header.logs_bloom, - mix_hash: header.mix_hash.unwrap_or_default(), - nonce: u64::from_be_bytes(header.nonce.unwrap_or_default().0), - number: header.number.ok_or(EthereumDataFormatError::PrimitiveError)?, - ommers_hash: header.uncles_hash, - parent_beacon_block_root: header.parent_beacon_block_root, - parent_hash: header.parent_hash, - receipts_root: header.receipts_root, - state_root: header.state_root, - timestamp: header.timestamp, - transactions_root: header.transactions_root, - // Withdrawals are not allowed so we push a None value - withdrawals_root: Default::default(), - }) -} - -pub fn rpc_to_primitive_block(block: reth_rpc_types::Block) -> Result { - let body = { - let transactions: Result, EthereumDataFormatError> = match block.transactions { - reth_rpc_types::BlockTransactions::Full(transactions) => transactions - .into_iter() - .map(|tx| { - let signature = tx.signature.ok_or(EthereumDataFormatError::PrimitiveError)?; - Ok(TransactionSigned::from_transaction_and_signature( - rpc_to_primitive_transaction(tx)?, - reth_primitives::Signature { - r: signature.r, - s: signature.s, - odd_y_parity: signature.y_parity.unwrap_or(reth_rpc_types::Parity(false)).0, - }, - )) - }) - .collect(), - reth_rpc_types::BlockTransactions::Hashes(_) | reth_rpc_types::BlockTransactions::Uncle => { - return Err(EthereumDataFormatError::PrimitiveError); - } - }; - transactions? - }; - // ⚠️ Kakarot does not support omners or withdrawals and returns default values for those fields ⚠️ - Ok(reth_primitives::Block { - header: rpc_to_primitive_header(block.header)?, - body, - ommers: Default::default(), - withdrawals: Some(Withdrawals::default()), - }) -} - #[cfg(test)] mod tests { + use crate::models::transaction::rpc_to_primitive_transaction; use std::str::FromStr; - use reth_primitives::{Address, Bloom, Bytes, B256, B64, U256}; + use reth_primitives::{Address, Block, Bloom, Bytes, TransactionSigned, B256, B64, U256}; use reth_rpc_types::{other::OtherFields, Parity, Signature}; - use super::*; - fn base_rpc_header() -> reth_rpc_types::Header { reth_rpc_types::Header { parent_hash: B256::from_str(&format!("0x{:0>64}", "01")).unwrap(), @@ -153,7 +82,7 @@ mod tests { state_root: B256::from_str(&format!("0x{:0>64}", "04")).unwrap(), transactions_root: B256::from_str(&format!("0x{:0>64}", "05")).unwrap(), receipts_root: B256::from_str(&format!("0x{:0>64}", "06")).unwrap(), - withdrawals_root: Some(B256::from_str(&format!("0x{:0>64}", "07")).unwrap()), + withdrawals_root: None, logs_bloom: Bloom::ZERO, difficulty: U256::ZERO, base_fee_per_gas: Some(8), @@ -173,6 +102,8 @@ mod tests { } fn base_rpc_transaction() -> reth_rpc_types::Transaction { + let access_list = reth_rpc_types::AccessList::default(); + reth_rpc_types::Transaction { hash: B256::default(), nonce: 1, @@ -196,7 +127,7 @@ mod tests { }), chain_id: Some(1), blob_versioned_hashes: Some(vec![]), - access_list: None, + access_list: Some(access_list), transaction_type: Some(2), other: serde_json::from_str("{}").unwrap(), } @@ -212,7 +143,7 @@ mod tests { base_rpc_transaction(), ]), size: None, - withdrawals: Some(Vec::default()), + withdrawals: None, other: OtherFields::default(), } } @@ -220,7 +151,7 @@ mod tests { #[test] fn test_rpc_to_primitive_block() { let block = base_rpc_block(); - let primitive_block = rpc_to_primitive_block(block).unwrap(); + let primitive_block = Block::try_from(block).unwrap(); assert_eq!(primitive_block.header.parent_hash, B256::from_str(&format!("0x{:0>64}", "01")).unwrap()); assert_eq!(primitive_block.header.ommers_hash, B256::from_str(&format!("0x{:0>64}", "02")).unwrap()); assert_eq!(primitive_block.header.beneficiary, Address::from_str(&format!("0x{:0>40}", "03")).unwrap()); @@ -271,7 +202,7 @@ mod tests { ) ] ); - assert_eq!(primitive_block.withdrawals, Some(Withdrawals::default())); + assert!(primitive_block.withdrawals.is_none()); assert_eq!(primitive_block.ommers, Vec::default()); } } diff --git a/tests/tests/debug_api.rs b/tests/tests/debug_api.rs index b5bf871dc..fe9a3a0be 100644 --- a/tests/tests/debug_api.rs +++ b/tests/tests/debug_api.rs @@ -1,14 +1,13 @@ #![cfg(feature = "testing")] -use alloy_rlp::{Decodable, Encodable}; +use alloy_rlp::Encodable; use kakarot_rpc::eth_provider::provider::EthereumProvider; -use kakarot_rpc::models::block::rpc_to_primitive_block; use kakarot_rpc::models::transaction::rpc_to_primitive_transaction; use kakarot_rpc::test_utils::fixtures::{katana, setup}; use kakarot_rpc::test_utils::katana::Katana; use kakarot_rpc::test_utils::mongo::{BLOCK_HASH, BLOCK_NUMBER, EIP1599_TX_HASH, EIP2930_TX_HASH, LEGACY_TX_HASH}; use kakarot_rpc::test_utils::rpc::start_kakarot_rpc_server; use reth_primitives::{ - BlockNumberOrTag, Bytes, Log, Receipt, ReceiptWithBloom, TransactionSigned, TransactionSignedEcRecovered, + Block, BlockNumberOrTag, Bytes, Log, Receipt, ReceiptWithBloom, TransactionSigned, TransactionSignedEcRecovered, }; use reth_rpc_types_compat::transaction::from_recovered_with_block_context; use rstest::*; @@ -476,17 +475,13 @@ async fn test_raw_block(#[future] katana: Katana, _setup: ()) { let response: Value = serde_json::from_str(&response).expect("Failed to deserialize response body"); let rpc_block: reth_rpc_types::Block = serde_json::from_value(response["result"].clone()).expect("Failed to deserialize result"); - let primitive_block = rpc_to_primitive_block(rpc_block).unwrap(); + let primitive_block = Block::try_from(rpc_block).unwrap(); // Encode primitive block and compare with the result of debug_getRawBlock let mut buf = Vec::new(); primitive_block.encode(&mut buf); assert_eq!(rlp_bytes.clone().unwrap(), Bytes::from(buf)); - // Decode encoded block and compare with the block from eth_getBlockByNumber - let decoded_block = reth_primitives::Block::decode(&mut rlp_bytes.unwrap().as_ref()).unwrap(); - assert_eq!(decoded_block, primitive_block); - // Stop the Kakarot RPC server. drop(server_handle); } @@ -571,7 +566,7 @@ async fn test_raw_header(#[future] katana: Katana, _setup: ()) { // Encode header into RLP bytes and assert equality with RLP bytes fetched by block number. let mut data = vec![]; - rpc_to_primitive_block(block.inner).unwrap().header.encode(&mut data); + Block::try_from(block.inner).unwrap().header.encode(&mut data); assert_eq!(rlp_bytes_by_block_number, data); // Stop the Kakarot RPC server.