diff --git a/crates/rpc-types-beacon/src/payload.rs b/crates/rpc-types-beacon/src/payload.rs index dab8c7aa8fe..4e2056178e0 100644 --- a/crates/rpc-types-beacon/src/payload.rs +++ b/crates/rpc-types-beacon/src/payload.rs @@ -129,68 +129,6 @@ struct BeaconOptimismPayloadAttributes { gas_limit: Option, } -/// A helper module for serializing and deserializing optimism payload attributes for the beacon -/// API. -/// -/// See docs for [beacon_api_payload_attributes]. -pub mod beacon_api_payload_attributes_optimism { - use super::*; - use alloy_rpc_types_engine::{OptimismPayloadAttributes, PayloadAttributes}; - - /// Serialize the payload attributes for the beacon API. - pub fn serialize( - payload_attributes: &OptimismPayloadAttributes, - serializer: S, - ) -> Result - where - S: Serializer, - { - let beacon_api_payload_attributes = BeaconPayloadAttributes { - timestamp: payload_attributes.payload_attributes.timestamp, - prev_randao: payload_attributes.payload_attributes.prev_randao, - suggested_fee_recipient: payload_attributes.payload_attributes.suggested_fee_recipient, - withdrawals: payload_attributes.payload_attributes.withdrawals.clone(), - parent_beacon_block_root: payload_attributes - .payload_attributes - .parent_beacon_block_root, - }; - - let op_beacon_api_payload_attributes = BeaconOptimismPayloadAttributes { - payload_attributes: beacon_api_payload_attributes, - transactions: payload_attributes.transactions.clone(), - no_tx_pool: payload_attributes.no_tx_pool, - gas_limit: payload_attributes.gas_limit, - }; - - op_beacon_api_payload_attributes.serialize(serializer) - } - - /// Deserialize the payload attributes for the beacon API. - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let beacon_api_payload_attributes = - BeaconOptimismPayloadAttributes::deserialize(deserializer)?; - Ok(OptimismPayloadAttributes { - payload_attributes: PayloadAttributes { - timestamp: beacon_api_payload_attributes.payload_attributes.timestamp, - prev_randao: beacon_api_payload_attributes.payload_attributes.prev_randao, - suggested_fee_recipient: beacon_api_payload_attributes - .payload_attributes - .suggested_fee_recipient, - withdrawals: beacon_api_payload_attributes.payload_attributes.withdrawals, - parent_beacon_block_root: beacon_api_payload_attributes - .payload_attributes - .parent_beacon_block_root, - }, - transactions: beacon_api_payload_attributes.transactions, - no_tx_pool: beacon_api_payload_attributes.no_tx_pool, - gas_limit: beacon_api_payload_attributes.gas_limit, - }) - } -} - /// A helper module for serializing and deserializing the payload attributes for the beacon API. /// /// The beacon API encoded object has equivalent fields to the diff --git a/crates/rpc-types-engine/src/lib.rs b/crates/rpc-types-engine/src/lib.rs index a8ef6b7a6d1..ef9e6fd932d 100644 --- a/crates/rpc-types-engine/src/lib.rs +++ b/crates/rpc-types-engine/src/lib.rs @@ -11,13 +11,10 @@ mod forkchoice; mod identification; #[cfg(feature = "jwt")] mod jwt; -mod optimism; pub mod payload; mod transition; -pub use self::{ - cancun::*, forkchoice::*, identification::*, optimism::*, payload::*, transition::*, -}; +pub use self::{cancun::*, forkchoice::*, identification::*, payload::*, transition::*}; #[cfg(feature = "jwt")] pub use self::jwt::*; diff --git a/crates/rpc-types-engine/src/optimism.rs b/crates/rpc-types-engine/src/optimism.rs deleted file mode 100644 index cabd4e268d5..00000000000 --- a/crates/rpc-types-engine/src/optimism.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::{BlobsBundleV1, ExecutionPayloadV3, ExecutionPayloadV4, PayloadAttributes}; -use alloy_primitives::{Bytes, B256, U256}; -use serde::{Deserialize, Serialize}; - -/// Optimism Payload Attributes -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct OptimismPayloadAttributes { - /// The payload attributes - #[serde(flatten)] - pub payload_attributes: PayloadAttributes, - /// Transactions is a field for rollups: the transactions list is forced into the block - #[serde(skip_serializing_if = "Option::is_none")] - pub transactions: Option>, - /// If true, the no transactions are taken out of the tx-pool, only transactions from the above - /// Transactions list will be included. - #[serde(skip_serializing_if = "Option::is_none")] - pub no_tx_pool: Option, - /// If set, this sets the exact gas limit the block produced with. - #[serde(skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub gas_limit: Option, -} - -/// This structure maps for the return value of `engine_getPayload` of the beacon chain spec, for -/// V3. -/// -/// See also: -/// [Optimism execution payload envelope v3] -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct OptimismExecutionPayloadEnvelopeV3 { - /// Execution payload V3 - pub execution_payload: ExecutionPayloadV3, - /// The expected value to be received by the feeRecipient in wei - pub block_value: U256, - /// The blobs, commitments, and proofs associated with the executed payload. - pub blobs_bundle: BlobsBundleV1, - /// Introduced in V3, this represents a suggestion from the execution layer if the payload - /// should be used instead of an externally provided one. - pub should_override_builder: bool, - /// Ecotone parent beacon block root - pub parent_beacon_block_root: B256, -} - -/// This structure maps for the return value of `engine_getPayload` of the beacon chain spec, for -/// V4. -/// -/// See also: -/// [Optimism execution payload envelope v4] -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct OptimismExecutionPayloadEnvelopeV4 { - /// Execution payload V4 - pub execution_payload: ExecutionPayloadV4, - /// The expected value to be received by the feeRecipient in wei - pub block_value: U256, - /// The blobs, commitments, and proofs associated with the executed payload. - pub blobs_bundle: BlobsBundleV1, - /// Introduced in V3, this represents a suggestion from the execution layer if the payload - /// should be used instead of an externally provided one. - pub should_override_builder: bool, - /// Ecotone parent beacon block root - pub parent_beacon_block_root: B256, -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::ExecutionPayloadInputV2; - - // - #[test] - fn deserialize_op_base_payload() { - let payload = r#"{"parentHash":"0x24e8df372a61cdcdb1a163b52aaa1785e0c869d28c3b742ac09e826bbb524723","feeRecipient":"0x4200000000000000000000000000000000000011","stateRoot":"0x9a5db45897f1ff1e620a6c14b0a6f1b3bcdbed59f2adc516a34c9a9d6baafa71","receiptsRoot":"0x8af6f74835d47835deb5628ca941d00e0c9fd75585f26dabdcb280ec7122e6af","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prevRandao":"0xf37b24eeff594848072a05f74c8600001706c83e489a9132e55bf43a236e42ec","blockNumber":"0xe3d5d8","gasLimit":"0x17d7840","gasUsed":"0xb705","timestamp":"0x65a118c0","extraData":"0x","baseFeePerGas":"0x7a0ff32","blockHash":"0xf5c147b2d60a519b72434f0a8e082e18599021294dd9085d7597b0ffa638f1c0","withdrawals":[],"transactions":["0x7ef90159a05ba0034ffdcb246703298224564720b66964a6a69d0d7e9ffd970c546f7c048094deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b90104015d8eb900000000000000000000000000000000000000000000000000000000009e1c4a0000000000000000000000000000000000000000000000000000000065a11748000000000000000000000000000000000000000000000000000000000000000a4b479e5fa8d52dd20a8a66e468b56e993bdbffcccf729223aabff06299ab36db000000000000000000000000000000000000000000000000000000000000000400000000000000000000000073b4168cc87f35cc239200a20eb841cded23493b000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240"]}"#; - let _payload = serde_json::from_str::(payload).unwrap(); - } - - #[test] - fn serde_roundtrip_execution_payload_envelope_v3() { - // pulled from a geth response getPayloadV3 in hive tests, modified to add a mock parent - // beacon block root. - let response = r#"{"executionPayload":{"parentHash":"0xe927a1448525fb5d32cb50ee1408461a945ba6c39bd5cf5621407d500ecc8de9","feeRecipient":"0x0000000000000000000000000000000000000000","stateRoot":"0x10f8a0830000e8edef6d00cc727ff833f064b1950afd591ae41357f97e543119","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prevRandao":"0xe0d8b4521a7da1582a713244ffb6a86aa1726932087386e2dc7973f43fc6cb24","blockNumber":"0x1","gasLimit":"0x2ffbd2","gasUsed":"0x0","timestamp":"0x1235","extraData":"0xd883010d00846765746888676f312e32312e30856c696e7578","baseFeePerGas":"0x342770c0","blockHash":"0x44d0fa5f2f73a938ebb96a2a21679eb8dea3e7b7dd8fd9f35aa756dda8bf0a8a","transactions":[],"withdrawals":[],"blobGasUsed":"0x0","excessBlobGas":"0x0"},"blockValue":"0x0","blobsBundle":{"commitments":[],"proofs":[],"blobs":[]},"shouldOverrideBuilder":false,"parentBeaconBlockRoot":"0xdead00000000000000000000000000000000000000000000000000000000beef"}"#; - let envelope: OptimismExecutionPayloadEnvelopeV3 = serde_json::from_str(response).unwrap(); - assert_eq!(serde_json::to_string(&envelope).unwrap(), response); - } -} diff --git a/crates/rpc-types-engine/src/payload.rs b/crates/rpc-types-engine/src/payload.rs index d79701657be..11087cf5177 100644 --- a/crates/rpc-types-engine/src/payload.rs +++ b/crates/rpc-types-engine/src/payload.rs @@ -1380,4 +1380,11 @@ mod tests { serde_json::from_str(input); assert!(payload_res.is_err()); } + + // + #[test] + fn deserialize_op_base_payload() { + let payload = r#"{"parentHash":"0x24e8df372a61cdcdb1a163b52aaa1785e0c869d28c3b742ac09e826bbb524723","feeRecipient":"0x4200000000000000000000000000000000000011","stateRoot":"0x9a5db45897f1ff1e620a6c14b0a6f1b3bcdbed59f2adc516a34c9a9d6baafa71","receiptsRoot":"0x8af6f74835d47835deb5628ca941d00e0c9fd75585f26dabdcb280ec7122e6af","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prevRandao":"0xf37b24eeff594848072a05f74c8600001706c83e489a9132e55bf43a236e42ec","blockNumber":"0xe3d5d8","gasLimit":"0x17d7840","gasUsed":"0xb705","timestamp":"0x65a118c0","extraData":"0x","baseFeePerGas":"0x7a0ff32","blockHash":"0xf5c147b2d60a519b72434f0a8e082e18599021294dd9085d7597b0ffa638f1c0","withdrawals":[],"transactions":["0x7ef90159a05ba0034ffdcb246703298224564720b66964a6a69d0d7e9ffd970c546f7c048094deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b90104015d8eb900000000000000000000000000000000000000000000000000000000009e1c4a0000000000000000000000000000000000000000000000000000000065a11748000000000000000000000000000000000000000000000000000000000000000a4b479e5fa8d52dd20a8a66e468b56e993bdbffcccf729223aabff06299ab36db000000000000000000000000000000000000000000000000000000000000000400000000000000000000000073b4168cc87f35cc239200a20eb841cded23493b000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240"]}"#; + let _payload = serde_json::from_str::(payload).unwrap(); + } } diff --git a/crates/rpc-types-eth/src/transaction/mod.rs b/crates/rpc-types-eth/src/transaction/mod.rs index df121b03569..1624bd21656 100644 --- a/crates/rpc-types-eth/src/transaction/mod.rs +++ b/crates/rpc-types-eth/src/transaction/mod.rs @@ -21,9 +21,6 @@ pub use common::TransactionInfo; mod error; pub use error::ConversionError; -pub mod optimism; -pub use optimism::OptimismTransactionReceiptFields; - mod receipt; pub use receipt::{AnyTransactionReceipt, TransactionReceipt}; diff --git a/crates/rpc-types-eth/src/transaction/optimism.rs b/crates/rpc-types-eth/src/transaction/optimism.rs deleted file mode 100644 index f6af3d64125..00000000000 --- a/crates/rpc-types-eth/src/transaction/optimism.rs +++ /dev/null @@ -1,181 +0,0 @@ -//! Misc Optimism-specific types. - -use alloy_primitives::B256; -use alloy_serde::OtherFields; -use serde::{Deserialize, Serialize}; - -/// Optimism specific transaction fields: -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] -#[doc(alias = "OptimismTxFields")] -#[serde(rename_all = "camelCase")] -pub struct OptimismTransactionFields { - /// Hash that uniquely identifies the source of the deposit. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub source_hash: Option, - /// The ETH value to mint on L2 - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub mint: Option, - /// Field indicating whether the transaction is a system transaction, and therefore - /// exempt from the L2 gas limit. - #[serde(default, skip_serializing_if = "Option::is_none")] - #[doc(alias = "is_system_transaction")] - pub is_system_tx: Option, - /// Deposit receipt version for Optimism deposit transactions, post-Canyon only - /// - /// - /// The deposit receipt version was introduced in Canyon to indicate an update to how - /// receipt hashes should be computed when set. The state transition process - /// ensures this is only set for post-Canyon deposit transactions. - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub deposit_receipt_version: Option, -} - -/// Additional fields for Optimism transaction receipts: -#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[doc(alias = "OptimismTxReceiptFields")] -pub struct OptimismTransactionReceiptFields { - /// Deposit nonce for deposit transactions post-regolith - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub deposit_nonce: Option, - /// Deposit receipt version for deposit transactions post-canyon - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub deposit_receipt_version: Option, - /// Present from pre-bedrock. L1 Basefee after Bedrock - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub l1_gas_price: Option, - /// Always null prior to the Ecotone hardfork. - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub l1_blob_base_fee: Option, - /// Present from pre-bedrock, deprecated as of Fjord. - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub l1_gas_used: Option, - /// Present from pre-bedrock. L1 fee for the transaction - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub l1_fee: Option, - /// Present from pre-bedrock to Ecotone. Nil after Ecotone - #[serde(default, skip_serializing_if = "Option::is_none", with = "l1_fee_scalar_serde")] - pub l1_fee_scalar: Option, - /// Always null prior to the Ecotone hardfork. - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub l1_base_fee_scalar: Option, - /// Always null prior to the Ecotone hardfork - #[serde(default, skip_serializing_if = "Option::is_none", with = "alloy_serde::quantity::opt")] - pub l1_blob_base_fee_scalar: Option, -} - -impl From for OtherFields { - fn from(value: OptimismTransactionFields) -> Self { - serde_json::to_value(value).unwrap().try_into().unwrap() - } -} - -impl From for OtherFields { - fn from(value: OptimismTransactionReceiptFields) -> Self { - serde_json::to_value(value).unwrap().try_into().unwrap() - } -} - -/// Serialize/Deserialize l1FeeScalar to/from string -mod l1_fee_scalar_serde { - use serde::{de, Deserialize}; - - pub(super) fn serialize(value: &Option, s: S) -> Result - where - S: serde::Serializer, - { - if let Some(v) = value { - return s.serialize_str(&v.to_string()); - } - s.serialize_none() - } - - pub(super) fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> - where - D: serde::Deserializer<'de>, - { - let s: Option = Option::deserialize(deserializer)?; - if let Some(s) = s { - return Ok(Some(s.parse::().map_err(de::Error::custom)?)); - } - - Ok(None) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use serde_json::{json, Value}; - - #[test] - fn serialize_empty_optimism_transaction_receipt_fields_struct() { - let op_fields = OptimismTransactionReceiptFields::default(); - - let json = serde_json::to_value(op_fields).unwrap(); - assert_eq!(json, json!({})); - } - - #[test] - fn serialize_l1_fee_scalar() { - let op_fields = OptimismTransactionReceiptFields { - l1_fee_scalar: Some(0.678), - ..OptimismTransactionReceiptFields::default() - }; - - let json = serde_json::to_value(op_fields).unwrap(); - - assert_eq!(json["l1FeeScalar"], serde_json::Value::String("0.678".to_string())); - } - - #[test] - fn deserialize_l1_fee_scalar() { - let json = json!({ - "l1FeeScalar": "0.678" - }); - - let op_fields: OptimismTransactionReceiptFields = serde_json::from_value(json).unwrap(); - assert_eq!(op_fields.l1_fee_scalar, Some(0.678f64)); - - let json = json!({ - "l1FeeScalar": Value::Null - }); - - let op_fields: OptimismTransactionReceiptFields = serde_json::from_value(json).unwrap(); - assert_eq!(op_fields.l1_fee_scalar, None); - - let json = json!({}); - - let op_fields: OptimismTransactionReceiptFields = serde_json::from_value(json).unwrap(); - assert_eq!(op_fields.l1_fee_scalar, None); - } - - #[test] - fn deserialize_op_receipt() { - let s = r#"{ - "blockHash": "0x70a8a64a0f8b141718f60e49c30f027cb9e4f91753d5f13a48d8e1ad263c08bf", - "blockNumber": "0x1185e55", - "contractAddress": null, - "cumulativeGasUsed": "0xc74f5e", - "effectiveGasPrice": "0x31b41b", - "from": "0x889ebdac39408782b5165c5185c1a769b4dd3ce6", - "gasUsed": "0x5208", - "l1BaseFeeScalar": "0x8dd", - "l1BlobBaseFee": "0x1", - "l1BlobBaseFeeScalar": "0x101c12", - "l1Fee": "0x125f723f3", - "l1GasPrice": "0x50f928b4", - "l1GasUsed": "0x640", - "logs": [ - ], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "status": "0x1", - "to": "0x7449061f45d7b39b3b80b4159286cd8682f60a3c", - "transactionHash": "0xca564948e3e825f65731424da063240eec34ba921dd117ac5d06b8c2e0b2d962", - "transactionIndex": "0x3e", - "type": "0x2" -} -"#; - let _receipt = serde_json::from_str::(s).unwrap(); - } -}