diff --git a/Cargo.toml b/Cargo.toml index 0b9fb13a9..2ec400191 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,8 +61,8 @@ alloy-network-primitives = { version = "0.6.3", default-features = false } alloy-rlp = { version = "0.3", default-features = false } # Alloy Core -alloy-sol-types = { version = "0.8.11", default-features = false } -alloy-primitives = { version = "0.8.11", default-features = false } +alloy-sol-types = { version = "0.8.12", default-features = false } +alloy-primitives = { version = "0.8.12", default-features = false } # Revm revm = "18.0.0" diff --git a/crates/consensus/src/hardforks/ecotone.rs b/crates/consensus/src/hardforks/ecotone.rs index bb70bb11a..66039ffa5 100644 --- a/crates/consensus/src/hardforks/ecotone.rs +++ b/crates/consensus/src/hardforks/ecotone.rs @@ -4,6 +4,7 @@ use crate::{OpTxEnvelope, TxDeposit}; use alloc::{string::String, vec, vec::Vec}; +use alloy_consensus::Sealable; use alloy_eips::eip2718::Encodable2718; use alloy_primitives::{address, bytes, Address, Bytes, TxKind, U256}; use spin::Lazy; @@ -72,91 +73,109 @@ impl super::Hardforks { // Deploy the L1 Block Contract let mut buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: DEPLOY_L1_BLOCK_SOURCE.source_hash(), - from: L1_BLOCK_DEPLOYER_ADDRESS, - to: TxKind::Create, - mint: 0.into(), - value: U256::ZERO, - gas_limit: 375_000, - is_system_transaction: false, - input: l1_block_deployment_bytecode, - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: DEPLOY_L1_BLOCK_SOURCE.source_hash(), + from: L1_BLOCK_DEPLOYER_ADDRESS, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 375_000, + is_system_transaction: false, + input: l1_block_deployment_bytecode, + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); // Deploy the Gas Price Oracle buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: DEPLOY_GAS_PRICE_ORACLE_SOURCE.source_hash(), - from: GAS_PRICE_ORACLE_DEPLOYER_ADDRESS, - to: TxKind::Create, - mint: 0.into(), - value: U256::ZERO, - gas_limit: 1_000_000, - is_system_transaction: false, - input: gas_price_oracle_deployment_bytecode, - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: DEPLOY_GAS_PRICE_ORACLE_SOURCE.source_hash(), + from: GAS_PRICE_ORACLE_DEPLOYER_ADDRESS, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 1_000_000, + is_system_transaction: false, + input: gas_price_oracle_deployment_bytecode, + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); // Update the l1 block proxy buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: UPDATE_L1_BLOCK_PROXY_SOURCE.source_hash(), - from: Address::default(), - to: TxKind::Call(L1_BLOCK_DEPLOYER_ADDRESS), - mint: 0.into(), - value: U256::ZERO, - gas_limit: 50_000, - is_system_transaction: false, - input: Self::upgrade_to_calldata(NEW_L1_BLOCK_ADDRESS), - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: UPDATE_L1_BLOCK_PROXY_SOURCE.source_hash(), + from: Address::default(), + to: TxKind::Call(L1_BLOCK_DEPLOYER_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 50_000, + is_system_transaction: false, + input: Self::upgrade_to_calldata(NEW_L1_BLOCK_ADDRESS), + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); // Update gas price oracle proxy buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: UPDATE_GAS_PRICE_ORACLE_SOURCE.source_hash(), - from: Address::default(), - to: TxKind::Call(GAS_PRICE_ORACLE_DEPLOYER_ADDRESS), - mint: 0.into(), - value: U256::ZERO, - gas_limit: 50_000, - is_system_transaction: false, - input: Self::upgrade_to_calldata(GAS_PRICE_ORACLE_ADDRESS), - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: UPDATE_GAS_PRICE_ORACLE_SOURCE.source_hash(), + from: Address::default(), + to: TxKind::Call(GAS_PRICE_ORACLE_DEPLOYER_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 50_000, + is_system_transaction: false, + input: Self::upgrade_to_calldata(GAS_PRICE_ORACLE_ADDRESS), + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); // Enable ecotone buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: ENABLE_ECOTONE_SOURCE.source_hash(), - from: L1_BLOCK_DEPLOYER_ADDRESS, - to: TxKind::Call(GAS_PRICE_ORACLE_ADDRESS), - mint: 0.into(), - value: U256::ZERO, - gas_limit: 80_000, - is_system_transaction: false, - input: ENABLE_ECOTONE_INPUT.into(), - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: ENABLE_ECOTONE_SOURCE.source_hash(), + from: L1_BLOCK_DEPLOYER_ADDRESS, + to: TxKind::Call(GAS_PRICE_ORACLE_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 80_000, + is_system_transaction: false, + input: ENABLE_ECOTONE_INPUT.into(), + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); // Deploy EIP4788 buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: BEACON_ROOTS_SOURCE.source_hash(), - from: EIP4788_FROM, - to: TxKind::Create, - mint: 0.into(), - value: U256::ZERO, - gas_limit: 250_000, - is_system_transaction: false, - input: eip4788_creation_data, - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: BEACON_ROOTS_SOURCE.source_hash(), + from: EIP4788_FROM, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 250_000, + is_system_transaction: false, + input: eip4788_creation_data, + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); diff --git a/crates/consensus/src/hardforks/fjord.rs b/crates/consensus/src/hardforks/fjord.rs index a3390665d..e85eba807 100644 --- a/crates/consensus/src/hardforks/fjord.rs +++ b/crates/consensus/src/hardforks/fjord.rs @@ -4,6 +4,7 @@ use crate::{OpTxEnvelope, TxDeposit}; use alloc::{string::String, vec, vec::Vec}; +use alloy_consensus::Sealable; use alloy_eips::eip2718::Encodable2718; use alloy_primitives::{address, Address, Bytes, TxKind, U256}; use spin::Lazy; @@ -58,46 +59,55 @@ impl super::Hardforks { let mut txs = vec![]; let mut buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: DEPLOY_FJORD_GAS_PRICE_ORACLE_SOURCE.source_hash(), - from: GAS_PRICE_ORACLE_FJORD_DEPLOYER_ADDRESS, - to: TxKind::Create, - mint: 0.into(), - value: U256::ZERO, - gas_limit: 1_450_000, - is_system_transaction: false, - input: Self::gas_price_oracle_deployment_bytecode(), - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: DEPLOY_FJORD_GAS_PRICE_ORACLE_SOURCE.source_hash(), + from: GAS_PRICE_ORACLE_FJORD_DEPLOYER_ADDRESS, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 1_450_000, + is_system_transaction: false, + input: Self::gas_price_oracle_deployment_bytecode(), + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); // Update the gas price oracle proxy. buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: UPDATE_FJORD_GAS_PRICE_ORACLE_SOURCE.source_hash(), - from: Address::ZERO, - to: TxKind::Call(GAS_PRICE_ORACLE_ADDRESS), - mint: 0.into(), - value: U256::ZERO, - gas_limit: 50_000, - is_system_transaction: false, - input: Self::upgrade_to_calldata(FJORD_GAS_PRICE_ORACLE_ADDRESS), - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: UPDATE_FJORD_GAS_PRICE_ORACLE_SOURCE.source_hash(), + from: Address::ZERO, + to: TxKind::Call(GAS_PRICE_ORACLE_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 50_000, + is_system_transaction: false, + input: Self::upgrade_to_calldata(FJORD_GAS_PRICE_ORACLE_ADDRESS), + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); // Enable Fjord buffer = Vec::new(); - OpTxEnvelope::Deposit(TxDeposit { - source_hash: ENABLE_FJORD_SOURCE.source_hash(), - from: L1_INFO_DEPOSITER_ADDRESS, - to: TxKind::Call(GAS_PRICE_ORACLE_ADDRESS), - mint: 0.into(), - value: U256::ZERO, - gas_limit: 90_000, - is_system_transaction: false, - input: SET_FJORD_METHOD_SIGNATURE.into(), - }) + OpTxEnvelope::Deposit( + TxDeposit { + source_hash: ENABLE_FJORD_SOURCE.source_hash(), + from: L1_INFO_DEPOSITER_ADDRESS, + to: TxKind::Call(GAS_PRICE_ORACLE_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 90_000, + is_system_transaction: false, + input: SET_FJORD_METHOD_SIGNATURE.into(), + } + .seal_slow(), + ) .encode_2718(&mut buffer); txs.push(Bytes::from(buffer)); diff --git a/crates/consensus/src/transaction/deposit.rs b/crates/consensus/src/transaction/deposit.rs index 3a245eb3f..6f06ba4e6 100644 --- a/crates/consensus/src/transaction/deposit.rs +++ b/crates/consensus/src/transaction/deposit.rs @@ -2,10 +2,11 @@ use super::OpTxType; use crate::DepositTransaction; -use alloy_consensus::Transaction; +use alloc::vec::Vec; +use alloy_consensus::{Sealable, Transaction}; use alloy_eips::eip2930::AccessList; use alloy_primitives::{ - Address, Bytes, ChainId, PrimitiveSignature as Signature, TxKind, B256, U256, + keccak256, Address, Bytes, ChainId, PrimitiveSignature as Signature, TxHash, TxKind, B256, U256, }; use alloy_rlp::{ Buf, BufMut, Decodable, Encodable, Error as DecodeError, Header, EMPTY_STRING_CODE, @@ -214,6 +215,13 @@ impl TxDeposit { self.eip2718_encode(out); } + /// Calculate the transaction hash. + pub fn tx_hash(&self) -> TxHash { + let mut buf = Vec::with_capacity(self.eip2718_encoded_length()); + self.eip2718_encode(&mut buf); + keccak256(&buf) + } + /// Returns the signature for the optimism deposit transactions, which don't include a /// signature. pub fn signature() -> Signature { @@ -305,22 +313,28 @@ impl Decodable for TxDeposit { } } +impl Sealable for TxDeposit { + fn hash_slow(&self) -> B256 { + self.tx_hash() + } +} + /// Deposit transactions don't have a signature, however, we include an empty signature in the /// response for better compatibility. /// /// This function can be used as `serialize_with` serde attribute for the [`TxDeposit`] and will /// flatten [`TxDeposit::signature`] into response. #[cfg(feature = "serde")] -pub fn serde_deposit_tx_rpc( - value: &TxDeposit, +pub fn serde_deposit_tx_rpc( + value: &T, serializer: S, ) -> Result { use serde::Serialize; #[derive(Serialize)] - struct SerdeHelper<'a> { + struct SerdeHelper<'a, T> { #[serde(flatten)] - value: &'a TxDeposit, + value: &'a T, #[serde(flatten)] signature: Signature, } diff --git a/crates/consensus/src/transaction/envelope.rs b/crates/consensus/src/transaction/envelope.rs index ef7385519..b31f16b82 100644 --- a/crates/consensus/src/transaction/envelope.rs +++ b/crates/consensus/src/transaction/envelope.rs @@ -1,5 +1,6 @@ use alloy_consensus::{ - transaction::RlpEcdsaTx, Signed, Transaction, TxEip1559, TxEip2930, TxEip7702, TxLegacy, + transaction::RlpEcdsaTx, Sealable, Sealed, Signed, Transaction, TxEip1559, TxEip2930, + TxEip7702, TxLegacy, }; use alloy_eips::{ eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718}, @@ -107,7 +108,7 @@ pub enum OpTxEnvelope { /// A [`TxEip7702`] tagged with type 4. Eip7702(Signed), /// A [`TxDeposit`] tagged with type 0x7E. - Deposit(TxDeposit), + Deposit(Sealed), } impl From> for OpTxEnvelope { @@ -136,6 +137,12 @@ impl From> for OpTxEnvelope { impl From for OpTxEnvelope { fn from(v: TxDeposit) -> Self { + v.seal_slow().into() + } +} + +impl From> for OpTxEnvelope { + fn from(v: Sealed) -> Self { Self::Deposit(v) } } @@ -341,7 +348,7 @@ impl OpTxEnvelope { #[inline] pub const fn is_system_transaction(&self) -> bool { match self { - Self::Deposit(tx) => tx.is_system_transaction, + Self::Deposit(tx) => tx.inner().is_system_transaction, _ => false, } } @@ -371,7 +378,7 @@ impl OpTxEnvelope { } /// Returns the [`TxDeposit`] variant if the transaction is a deposit transaction. - pub const fn as_deposit(&self) -> Option<&TxDeposit> { + pub const fn as_deposit(&self) -> Option<&Sealed> { match self { Self::Deposit(tx) => Some(tx), _ => None, @@ -423,7 +430,7 @@ impl Decodable2718 for OpTxEnvelope { OpTxType::Eip2930 => Ok(Self::Eip2930(TxEip2930::rlp_decode_signed(buf)?)), OpTxType::Eip1559 => Ok(Self::Eip1559(TxEip1559::rlp_decode_signed(buf)?)), OpTxType::Eip7702 => Ok(Self::Eip7702(TxEip7702::rlp_decode_signed(buf)?)), - OpTxType::Deposit => Ok(Self::Deposit(TxDeposit::decode(buf)?)), + OpTxType::Deposit => Ok(Self::Deposit(TxDeposit::decode(buf)?.seal_slow())), OpTxType::Legacy => { Err(alloy_rlp::Error::Custom("type-0 eip2718 transactions are not supported") .into()) @@ -469,6 +476,16 @@ impl Encodable2718 for OpTxEnvelope { } } } + + fn trie_hash(&self) -> B256 { + match self { + Self::Legacy(tx) => *tx.hash(), + Self::Eip1559(tx) => *tx.hash(), + Self::Eip2930(tx) => *tx.hash(), + Self::Eip7702(tx) => *tx.hash(), + Self::Deposit(tx) => tx.seal(), + } + } } #[cfg(feature = "serde")] @@ -508,7 +525,7 @@ mod serde_from { #[serde(rename = "0x4", alias = "0x04")] Eip7702(Signed), #[serde(rename = "0x7e", alias = "0x7E", serialize_with = "crate::serde_deposit_tx_rpc")] - Deposit(TxDeposit), + Deposit(Sealed), } impl From for OpTxEnvelope { @@ -554,18 +571,18 @@ mod tests { #[test] fn test_tx_gas_limit() { let tx = TxDeposit { gas_limit: 1, ..Default::default() }; - let tx_envelope = OpTxEnvelope::Deposit(tx); + let tx_envelope = OpTxEnvelope::Deposit(tx.seal_slow()); assert_eq!(tx_envelope.gas_limit(), 1); } #[test] fn test_system_transaction() { let mut tx = TxDeposit { is_system_transaction: true, ..Default::default() }; - let tx_envelope = OpTxEnvelope::Deposit(tx.clone()); + let tx_envelope = OpTxEnvelope::Deposit(tx.clone().seal_slow()); assert!(tx_envelope.is_system_transaction()); tx.is_system_transaction = false; - let tx_envelope = OpTxEnvelope::Deposit(tx); + let tx_envelope = OpTxEnvelope::Deposit(tx.seal_slow()); assert!(!tx_envelope.is_system_transaction()); } @@ -581,7 +598,7 @@ mod tests { input: Bytes::from(vec![5]), is_system_transaction: false, }; - let tx_envelope = OpTxEnvelope::Deposit(tx); + let tx_envelope = OpTxEnvelope::Deposit(tx.seal_slow()); let encoded = tx_envelope.encoded_2718(); let decoded = OpTxEnvelope::decode_2718(&mut encoded.as_ref()).unwrap(); assert_eq!(encoded.len(), tx_envelope.encode_2718_len()); @@ -601,7 +618,7 @@ mod tests { mint: Some(u128::MAX), is_system_transaction: false, }; - let tx_envelope = OpTxEnvelope::Deposit(tx); + let tx_envelope = OpTxEnvelope::Deposit(tx.seal_slow()); let serialized = serde_json::to_string(&tx_envelope).unwrap(); let deserialized: OpTxEnvelope = serde_json::from_str(&serialized).unwrap(); diff --git a/crates/consensus/src/transaction/typed.rs b/crates/consensus/src/transaction/typed.rs index 353f41b8a..fec76996a 100644 --- a/crates/consensus/src/transaction/typed.rs +++ b/crates/consensus/src/transaction/typed.rs @@ -65,7 +65,7 @@ impl From for OpTypedTransaction { OpTxEnvelope::Eip2930(tx) => Self::Eip2930(tx.strip_signature()), OpTxEnvelope::Eip1559(tx) => Self::Eip1559(tx.strip_signature()), OpTxEnvelope::Eip7702(tx) => Self::Eip7702(tx.strip_signature()), - OpTxEnvelope::Deposit(tx) => Self::Deposit(tx), + OpTxEnvelope::Deposit(tx) => Self::Deposit(tx.into_inner()), } } } diff --git a/crates/protocol/src/block_info.rs b/crates/protocol/src/block_info.rs index 124a3efe1..f4216e1a9 100644 --- a/crates/protocol/src/block_info.rs +++ b/crates/protocol/src/block_info.rs @@ -8,7 +8,7 @@ use alloc::{ }; use alloy_consensus::Header; use alloy_eips::BlockNumHash; -use alloy_primitives::{address, Address, Bytes, TxKind, B256, U256}; +use alloy_primitives::{address, Address, Bytes, Sealable, TxKind, B256, U256}; use op_alloy_consensus::{OpTxEnvelope, TxDeposit}; use op_alloy_genesis::{RollupConfig, SystemConfig}; @@ -260,7 +260,7 @@ impl L1BlockInfoTx { deposit_tx.gas_limit = REGOLITH_SYSTEM_TX_GAS; } - Ok((l1_info, OpTxEnvelope::Deposit(deposit_tx))) + Ok((l1_info, OpTxEnvelope::Deposit(deposit_tx.seal_slow()))) } /// Decodes the [L1BlockInfoEcotone] object from ethereum transaction calldata. diff --git a/crates/protocol/src/deposits.rs b/crates/protocol/src/deposits.rs index a8235597e..dfe611cc7 100644 --- a/crates/protocol/src/deposits.rs +++ b/crates/protocol/src/deposits.rs @@ -1,11 +1,9 @@ //! Contains deposit transaction types and helper methods. use alloc::{string::String, vec::Vec}; -use alloy_eips::eip2718::Encodable2718; use alloy_primitives::{b256, keccak256, Address, Bytes, Log, TxKind, B256, U256, U64}; -use alloy_rlp::Encodable; use core::fmt::Display; -use op_alloy_consensus::{OpTxEnvelope, TxDeposit}; +use op_alloy_consensus::TxDeposit; /// Deposit log event abi signature. pub const DEPOSIT_EVENT_ABI: &str = "TransactionDeposited(address,address,uint256,bytes)"; @@ -337,9 +335,8 @@ pub fn decode_deposit(block_hash: B256, index: usize, log: &Log) -> Result for OpTransactionRequest { } } +impl From> for OpTransactionRequest { + fn from(value: Sealed) -> Self { + value.into_inner().into() + } +} + impl From> for OpTransactionRequest where T: SignableTransaction + Into,