diff --git a/bin/programs/client/map.json b/bin/programs/client/map.json deleted file mode 100644 index b7fe9d68d..000000000 --- a/bin/programs/client/map.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "0x45de91b2882e40e5d2966e9ef12a108c84ec73fd": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0xdc6ff44d5d932cbd77b52e5612ba0529dc6226f1": "0xeec1a4a835417cb844a9af71d96866f5951f545230da929fe404b8eaaeacf88d", - "0x1ab4973a48dc892cd9971ece8e01dcc7688f8f23": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x7f5c764cbc14f9669b88837ca1490cca17c31607": "0x8b7649cb868ee89989d1663868843d1565745abc26ce61babb63f5457c945b27", - "0xcbf74b5e15404cdc8d8391ffdbf2cd48971a20bd": "0xd49aff2ca768247c2b008d7748fea94e584578eb0aaf9d5c6c9cdfd8a6dc21cf", - "0x1f764262a8d96239275b6955f1b0c2e490e78dfd": "0xbbdb4d54e3e6b2f14261ab2924082422c9dc5063bf6e348066a0cbe3d3c9e8fa", - "0x420000000000000000000000000000000000001a": "0x1537094ddec5fc400e139c8ffc199092352a6e326094f78ff335d492c129390d", - "0x7b46ffbc976db2f94c3b3cdd9ebbe4ab50e3d77d": "0x09effb681b854cd97cff81cdf446a5b7b8541dfc2b2c9a7bd4de627facdda3f8", - "0x036db1e5d1a94acd2349a21db1c3c5699995f111": "0x9eb89f8a095e2b1b7aea8f72b6d6b9f8c88c493ae30fb6582cfad4a9dbcca943", - "0xfcd04b8f8e8ad520e3c494b6b573f49ad4c9853d": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0xdea125ffc58cbfc448654b9a7697aca7501e5a2d": "0x49f18286abc1bf779e91e486128d2e4899586b494168d6a39f40d525cf1a1a2b", - "0xecde1338f64e10599726ed13ea2727572663b409": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58": "0x5f929f1f1b63287ffa701e18fa8f07aed4a0e79f4a46cd918178edc56f0f9282", - "0x4200000000000000000000000000000000000015": "0x9f1b48703ccbcd75f0485d89b02d820616194237c4aa9878f5911f118e210d48", - "0x5c8054979cca5e921f893b22bee7a900a29792b9": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x90a32be26009dfb0a36b3be2ec9f50a9fa0bf223": "0xe0d974b4bfb5e0477d561002da5d43d82d4466971d360940848ad912d8144041", - "0xe168f61309fb6bd28ff05a24df28da856a53b587": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x05fa18acc756d83ce08e0dd8db44b62b904190e3": "0x20155e3c3113e0b3f0441b50bb6941399ff1903adfacf7be4ea5b72da6ee566c", - "0x314c9258a47fcaf9a59a0eb2e02d8b503dab0984": "0x2bca98d49c9fc20f26da1cb24deacd347b8e87e0a271a20a4d61b499fab00a64", - "0x8c7c2c3362a42308bb5c368677ad321d11693b81": "0x992d1f33bdd5dc6c555db0c6e71465d644b27b106ee0395f8549fb26f774d378", - "0x8ff4b27b47d3fd7da6f13a1e3592aba572b673a5": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x6b3c6afc0a5cff7c98db387d3b9bea85fb220966": "0xca9927d3c4a01dedace00162eefd94c2d9b6a50a4de2076ba031f2d7734b7537", - "0x0c7271b6dafb7adfccebc04a1c05160c11cc3786": "0xe2c134ec3c4f6b6d9c1252a6e03a83b16aea44f2249533f933409354baa1b56a", - "0xc366b56a90903b87fdb531ec43b2bf82ed326c7c": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x05775d945a6f3096205fe7b7a2409e466fb07783": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x4200000000000000000000000000000000000019": "0x81a8d4b85cb660c524fffe5fa6805cee260c2b9c9c8bd5d309c4def157940080", - "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "0x4200000000000000000000000000000000000011": "0x4ff6aca680d5f9bd99cfc4056237d3124c50234d897e4b377c56cf9ae2452471", - "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": "0x7c42f6b5a0520f682655b69cad5c489a03e5b3f0b1259b6219142814657ba777", - "0xf7bd944cd6d51a8b7dab54785608d8bda08f9155": "0xc7651e2b3dabdbb0027ff24c7dc0c84e664085e5f6879d6d58b27435c9c86f41" -} \ No newline at end of file diff --git a/bin/programs/client/src/l2/executor/canyon.rs b/bin/programs/client/src/l2/executor/canyon.rs index 1894159bf..5687b26c9 100644 --- a/bin/programs/client/src/l2/executor/canyon.rs +++ b/bin/programs/client/src/l2/executor/canyon.rs @@ -1,5 +1,6 @@ //! Contains logic specific to Canyon hardfork activation. +use alloy_consensus::Header; use alloy_primitives::{address, b256, hex, Address, Bytes, B256}; use kona_derive::types::RollupConfig; use revm::{ @@ -24,14 +25,14 @@ pub(crate) fn ensure_create2_deployer_canyon( db: &mut State, config: &RollupConfig, timestamp: u64, + parent_header: &Header, ) -> Result<(), DB::Error> where DB: revm::Database, { // If the canyon hardfork is active at the current timestamp, and it was not active at the - // previous block timestamp (heuristically, block time is not perfectly constant at 2s), and the - // chain is an optimism chain, then we need to force-deploy the create2 deployer contract. - if config.is_canyon_active(timestamp) && !config.is_canyon_active(timestamp.saturating_sub(2)) { + // previous block timestamp, then we need to force-deploy the create2 deployer contract. + if config.is_canyon_active(timestamp) && !config.is_canyon_active(parent_header.timestamp) { // Load the create2 deployer account from the cache. let acc = db.load_cache_account(CREATE_2_DEPLOYER_ADDR)?; diff --git a/bin/programs/client/src/l2/executor/mod.rs b/bin/programs/client/src/l2/executor/mod.rs index c4d34421d..67d18f199 100644 --- a/bin/programs/client/src/l2/executor/mod.rs +++ b/bin/programs/client/src/l2/executor/mod.rs @@ -30,6 +30,8 @@ pub(crate) use canyon::ensure_create2_deployer_canyon; mod util; pub(crate) use util::{logs_bloom, wrap_receipt_with_bloom}; +use self::util::{extract_tx_gas_limit, is_system_transaction}; + /// The block executor for the L2 client program. Operates off of a [TrieDB] backed [State], /// allowing for stateless block execution of OP Stack blocks. #[derive(Debug)] @@ -103,8 +105,12 @@ where )?; // Ensure that the create2 contract is deployed upon transition to the Canyon hardfork. - // TODO(clabby): Pass parent header - ensure_create2_deployer_canyon(&mut self.state, self.config.as_ref(), payload.timestamp)?; + ensure_create2_deployer_canyon( + &mut self.state, + self.config.as_ref(), + payload.timestamp, + &self.parent_header, + )?; // Construct the EVM with the given configuration. // TODO(clabby): Accelerate precompiles w/ custom precompile handler. @@ -125,11 +131,12 @@ where // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. // let block_available_gas = gas_limit - cumulative_gas_used; - // if transaction.gas_limit() > block_available_gas - // && (is_regolith || !transaction.is_system_transaction()) - // { - // anyhow::bail!("Transaction gas limit exceeds block gas limit") - // } + let block_available_gas = (gas_limit - cumulative_gas_used) as u128; + if extract_tx_gas_limit(&transaction) > block_available_gas && + (is_regolith || !is_system_transaction(&transaction)) + { + anyhow::bail!("Transaction gas limit exceeds block gas limit") + } // Reject any EIP-4844 transactions. if matches!(transaction, OpTxEnvelope::Eip4844(_)) { @@ -277,8 +284,7 @@ where /// The active [SpecId] for the executor. fn revm_spec_id(&self, timestamp: u64) -> SpecId { if self.config.is_fjord_active(timestamp) { - // TODO(clabby): Replace w/ Fjord Spec ID, once in a revm release. - SpecId::ECOTONE + SpecId::FJORD } else if self.config.is_ecotone_active(timestamp) { SpecId::ECOTONE } else if self.config.is_canyon_active(timestamp) { diff --git a/bin/programs/client/src/l2/executor/util.rs b/bin/programs/client/src/l2/executor/util.rs index b6711166f..f11f1c9cb 100644 --- a/bin/programs/client/src/l2/executor/util.rs +++ b/bin/programs/client/src/l2/executor/util.rs @@ -1,7 +1,8 @@ //! Contains utilities for the L2 executor. +use alloy_consensus::Transaction; use alloy_primitives::{Bloom, Log}; -use op_alloy_consensus::{OpReceiptEnvelope, OpReceiptWithBloom, OpTxType}; +use op_alloy_consensus::{OpReceiptEnvelope, OpReceiptWithBloom, OpTxEnvelope, OpTxType}; /// Compute the logs bloom filter for the given logs. pub(crate) fn logs_bloom<'a>(logs: impl IntoIterator) -> Bloom { @@ -28,3 +29,23 @@ pub(crate) fn wrap_receipt_with_bloom( OpTxType::Deposit => OpReceiptEnvelope::Deposit(receipt), } } + +/// Extract the gas limit from an [OpTxEnvelope]. +pub(crate) fn extract_tx_gas_limit(tx: &OpTxEnvelope) -> u128 { + match tx { + OpTxEnvelope::Legacy(tx) => tx.tx().gas_limit, + OpTxEnvelope::Eip2930(tx) => tx.tx().gas_limit, + OpTxEnvelope::Eip1559(tx) => tx.tx().gas_limit, + OpTxEnvelope::Eip4844(tx) => tx.tx().gas_limit(), + OpTxEnvelope::Deposit(tx) => tx.gas_limit, + _ => unreachable!(), + } +} + +/// Returns whether or not an [OpTxEnvelope] is a system transaction. +pub(crate) fn is_system_transaction(tx: &OpTxEnvelope) -> bool { + match tx { + OpTxEnvelope::Deposit(tx) => tx.is_system_transaction, + _ => false, + } +} diff --git a/crates/mpt/src/db/mod.rs b/crates/mpt/src/db/mod.rs index 12bafea60..70dddbc5f 100644 --- a/crates/mpt/src/db/mod.rs +++ b/crates/mpt/src/db/mod.rs @@ -213,13 +213,7 @@ where trie_account.encode(&mut account_buf); // Insert or update the account in the trie. - if let Some(account_rlp_ref) = self.root_node.open(&account_path, &self.fetcher)? { - // Update the existing account in the trie. - *account_rlp_ref = account_buf.into(); - } else { - // Insert the new account into the trie. - self.root_node.insert(&account_path, account_buf.into(), &self.fetcher)?; - } + self.root_node.insert(&account_path, account_buf.into(), &self.fetcher)?; } Ok(()) @@ -247,16 +241,11 @@ where // Insert or update the storage slot in the trie. let hashed_slot_key = Nibbles::unpack(keccak256(index.to_be_bytes::<32>().as_slice())); - if let Some(storage_slot_rlp) = storage_root.open(&hashed_slot_key, fetcher)? { - if value.is_zero() { - // If the storage slot is being set to zero, prune it from the trie. - storage_root.delete(&hashed_slot_key, fetcher)?; - } else { - // Otherwise, update the storage slot. - *storage_slot_rlp = rlp_buf.into(); - } + if value.is_zero() { + // If the storage slot is being set to zero, prune it from the trie. + storage_root.delete(&hashed_slot_key, fetcher)?; } else { - // If the storage slot does not exist, insert it. + // Otherwise, update the storage slot. storage_root.insert(&hashed_slot_key, rlp_buf.into(), fetcher)?; } diff --git a/crates/mpt/src/node.rs b/crates/mpt/src/node.rs index 112ab8fae..11b4ff894 100644 --- a/crates/mpt/src/node.rs +++ b/crates/mpt/src/node.rs @@ -114,7 +114,7 @@ impl TrieNode { /// length. Alternatively, if the [TrieNode] is a [TrieNode::Blinded] node already, it /// is left as-is. pub fn blind(&mut self) { - if self.length() >= 32 && !matches!(self, TrieNode::Blinded { .. }) { + if self.length() >= B256::ZERO.len() && !matches!(self, TrieNode::Blinded { .. }) { let mut rlp_buf = Vec::with_capacity(self.length()); self.encode(&mut rlp_buf); *self = TrieNode::Blinded { commitment: keccak256(rlp_buf) } @@ -362,14 +362,10 @@ impl TrieNode { return Ok(()); } - if remaining_nibbles.starts_with(prefix) { - node.delete_inner(path, nibble_offset + prefix.len(), fetcher)?; + node.delete_inner(path, nibble_offset + prefix.len(), fetcher)?; - // Simplify extension if possible after the deletion - self.collapse_if_possible(fetcher) - } else { - anyhow::bail!("Key does not exist in trie (extension node mismatch)") - } + // Simplify extension if possible after the deletion + self.collapse_if_possible(fetcher) } TrieNode::Branch { stack } => { let branch_nibble = remaining_nibbles[0] as usize; @@ -454,9 +450,6 @@ impl TrieNode { } _ => {} }; - } else if non_empty_children.is_empty() { - // If all children are empty, convert the branch into an empty node. - *self = TrieNode::Empty; } } _ => {} @@ -541,7 +534,7 @@ impl TrieNode { /// than a [B256]. fn blinded_length(&self) -> usize { let encoded_len = self.length(); - if encoded_len >= 32 && !matches!(self, TrieNode::Blinded { .. }) { + if encoded_len >= B256::ZERO.len() && !matches!(self, TrieNode::Blinded { .. }) { B256::ZERO.length() } else { encoded_len @@ -572,15 +565,12 @@ impl Encodable for TrieNode { // In branch nodes, if an element is longer than 32 bytes in length, it is blinded. // Assuming we have an open trie node, we must re-hash the elements // that are longer than 32 bytes in length. - let blinded_nodes = stack - .iter() - .cloned() - .map(|mut node| { - node.blind(); - node - }) - .collect::>(); - blinded_nodes.encode(out); + Header { list: true, payload_length: self.payload_length() }.encode(out); + stack.iter().for_each(|node| { + let mut blinded = node.clone(); + blinded.blind(); + blinded.encode(out); + }); } } }