diff --git a/cmd/ethrex/l2/command.rs b/cmd/ethrex/l2/command.rs index 12b967ef29..a9637198b1 100644 --- a/cmd/ethrex/l2/command.rs +++ b/cmd/ethrex/l2/command.rs @@ -441,7 +441,7 @@ impl Command { first_block: first_block_number, last_block: new_block.number, state_root: new_block.state_root, - deposit_logs_hash: H256::zero(), + privileged_transactions_hash: H256::zero(), message_hashes, blobs_bundle: BlobsBundle::empty(), commit_tx: None, diff --git a/crates/blockchain/metrics/l2/metrics.rs b/crates/blockchain/metrics/l2/metrics.rs index b99edbcba9..deca6d5361 100644 --- a/crates/blockchain/metrics/l2/metrics.rs +++ b/crates/blockchain/metrics/l2/metrics.rs @@ -128,7 +128,7 @@ pub enum MetricsBlockType { } pub enum MetricsOperationType { - Deposits, + PrivilegedTransactions, L1Messages, } @@ -146,7 +146,7 @@ impl MetricsBlockType { impl MetricsOperationType { fn to_str(&self) -> &str { match self { - MetricsOperationType::Deposits => "processedDeposits", + MetricsOperationType::PrivilegedTransactions => "processedPrivilegedTransactions", MetricsOperationType::L1Messages => "processedMessages", } } diff --git a/crates/common/types/batch.rs b/crates/common/types/batch.rs index c56f9872c3..422782f7fe 100644 --- a/crates/common/types/batch.rs +++ b/crates/common/types/batch.rs @@ -10,7 +10,7 @@ pub struct Batch { pub first_block: u64, pub last_block: u64, pub state_root: H256, - pub deposit_logs_hash: H256, + pub privileged_transactions_hash: H256, pub message_hashes: Vec, #[serde(skip_serializing)] pub blobs_bundle: BlobsBundle, diff --git a/crates/common/types/transaction.rs b/crates/common/types/transaction.rs index f5c5939569..30e8b5b07c 100644 --- a/crates/common/types/transaction.rs +++ b/crates/common/types/transaction.rs @@ -1271,7 +1271,7 @@ impl Transaction { pub fn compute_hash(&self) -> H256 { if let Transaction::PrivilegedL2Transaction(tx) = self { - return tx.get_deposit_hash().unwrap_or_default(); + return tx.get_privileged_hash().unwrap_or_default(); } keccak_hash::keccak(self.encode_canonical_to_vec()) } @@ -1354,10 +1354,10 @@ impl TxType { } impl PrivilegedL2Transaction { - /// Returns the formatted hash of the deposit transaction, - /// or None if the transaction is not a deposit. - /// The hash is computed as keccak256(to || value || deposit_id == nonce || from || gas_limit || keccak256(calldata)) - pub fn get_deposit_hash(&self) -> Option { + /// Returns the formatted hash of the privileged transaction, + /// or None if the transaction is not a privileged transaction. + /// The hash is computed as keccak256(from || to || transaction_id || value || gas_limit || keccak256(calldata)) + pub fn get_privileged_hash(&self) -> Option { // Should this function be changed? let to = match self.to { TxKind::Call(to) => to, @@ -1367,16 +1367,16 @@ impl PrivilegedL2Transaction { let value = self.value.to_big_endian(); // The nonce should be a U256, - // in solidity the depositId is a U256. + // in solidity the transactionId is a U256. let u256_nonce = U256::from(self.nonce); let nonce = u256_nonce.to_big_endian(); Some(keccak_hash::keccak( [ + self.from.as_bytes(), to.as_bytes(), - &value, &nonce, - self.from.as_bytes(), + &value, &U256::from(self.gas_limit).to_big_endian(), keccak(&self.data).as_bytes(), ] diff --git a/crates/l2/based/block_fetcher.rs b/crates/l2/based/block_fetcher.rs index 6685aa56d6..f9fb6ba483 100644 --- a/crates/l2/based/block_fetcher.rs +++ b/crates/l2/based/block_fetcher.rs @@ -8,8 +8,8 @@ use ethrex_common::{ }, }; use ethrex_l2_common::{ - deposits::compute_deposit_logs_hash, l1_messages::{L1Message, get_block_l1_messages, get_l1_message_hash}, + privileged_transactions::compute_privileged_transactions_hash, state_diff::prepare_state_diff, }; use ethrex_rlp::decode::RLPDecode; @@ -52,8 +52,10 @@ pub enum BlockFetcherError { EvmError(#[from] ethrex_vm::EvmError), #[error("Failed to produce the blob bundle")] BlobBundleError, - #[error("Failed to compute deposit logs hash: {0}")] - DepositError(#[from] ethrex_l2_common::deposits::DepositError), + #[error("Failed to compute privileged transactions hash: {0}")] + PrivilegedTransactionError( + #[from] ethrex_l2_common::privileged_transactions::PrivilegedTransactionError, + ), #[error("Spawned GenServer Error")] GenServerError(spawned_concurrency::GenServerError), } @@ -343,7 +345,7 @@ fn decode_batch_from_calldata(calldata: &[u8]) -> Result, BlockFetche // bytes32 newStateRoot, // bytes32 stateDiffKZGVersionedHash, // bytes32 messagesLogsMerkleRoot, - // bytes32 processedDepositLogsRollingHash, + // bytes32 processedPrivilegedTransactionsRollingHash, // bytes[] calldata _rlpEncodedBlocks // ) external; @@ -352,7 +354,7 @@ fn decode_batch_from_calldata(calldata: &[u8]) -> Result, BlockFetche // || 32 bytes (new state root) 36..68 // || 32 bytes (state diff KZG versioned hash) 68..100 // || 32 bytes (messages logs merkle root) 100..132 - // || 32 bytes (processed deposit logs rolling hash) 132..164 + // || 32 bytes (processed privileged transactions rolling hash) 132..164 let batch_length_in_blocks = U256::from_big_endian(calldata.get(196..228).ok_or( BlockFetcherError::WrongBatchCalldata("Couldn't get batch length bytes".to_owned()), @@ -489,29 +491,29 @@ async fn get_batch( batch_number: U256, commit_tx: H256, ) -> Result { - let deposits: Vec = batch + let privileged_transactions: Vec = batch .iter() .flat_map(|block| { block.body.transactions.iter().filter_map(|tx| { if let Transaction::PrivilegedL2Transaction(tx) = tx { Some(tx.clone()) - // tx.get_deposit_hash() } else { None } }) }) .collect(); - let deposit_log_hashes = deposits + let privileged_transaction_hashes = privileged_transactions .iter() - .filter_map(|tx| tx.get_deposit_hash()) + .filter_map(|tx| tx.get_privileged_hash()) .collect(); let mut messages = Vec::new(); for block in batch { let block_messages = extract_block_messages(state, block.header.number).await?; messages.extend(block_messages); } - let deposit_logs_hash = compute_deposit_logs_hash(deposit_log_hashes)?; + let privileged_transactions_hash = + compute_privileged_transactions_hash(privileged_transaction_hashes)?; let first_block = batch.first().ok_or(BlockFetcherError::InternalError( "Batch is empty. This shouldn't happen.".to_owned(), @@ -558,7 +560,7 @@ async fn get_batch( last_block.header.clone(), &parent_db, &messages, - &deposits, + &privileged_transactions, acc_account_updates.into_values().collect(), ) .map_err(|_| BlockFetcherError::BlobBundleError)?; @@ -571,7 +573,7 @@ async fn get_batch( first_block: first_block.header.number, last_block: last_block.header.number, state_root: new_state_root, - deposit_logs_hash, + privileged_transactions_hash, message_hashes: get_batch_message_hashes(state, batch).await?, blobs_bundle, commit_tx: Some(commit_tx), diff --git a/crates/l2/common/src/lib.rs b/crates/l2/common/src/lib.rs index 876f3f802b..0b8c9120d6 100644 --- a/crates/l2/common/src/lib.rs +++ b/crates/l2/common/src/lib.rs @@ -1,6 +1,6 @@ pub mod calldata; -pub mod deposits; pub mod l1_messages; pub mod merkle_tree; +pub mod privileged_transactions; pub mod prover; pub mod state_diff; diff --git a/crates/l2/common/src/deposits.rs b/crates/l2/common/src/privileged_transactions.rs similarity index 62% rename from crates/l2/common/src/deposits.rs rename to crates/l2/common/src/privileged_transactions.rs index e6bba11fdc..f000f47fca 100644 --- a/crates/l2/common/src/deposits.rs +++ b/crates/l2/common/src/privileged_transactions.rs @@ -4,13 +4,13 @@ use keccak_hash::keccak; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct DepositLog { +pub struct PrivilegedTransactionLog { pub address: Address, pub amount: U256, pub nonce: u64, } -impl DepositLog { +impl PrivilegedTransactionLog { pub fn encode(&self) -> Vec { let mut encoded = Vec::new(); encoded.extend(self.address.0); @@ -20,14 +20,14 @@ impl DepositLog { } #[derive(Debug, thiserror::Error)] -pub enum DepositError { - #[error("Failed to decode deposit hash")] +pub enum PrivilegedTransactionError { + #[error("Failed to decode transaction hash")] FailedToDecodeHash, #[error("Length does not fit in u16")] LengthTooLarge(#[from] std::num::TryFromIntError), } -pub fn get_block_deposits(txs: &[Transaction]) -> Vec { +pub fn get_block_privileged_transactions(txs: &[Transaction]) -> Vec { txs.iter() .filter_map(|tx| match tx { Transaction::PrivilegedL2Transaction(tx) => Some(tx.clone()), @@ -36,18 +36,20 @@ pub fn get_block_deposits(txs: &[Transaction]) -> Vec { .collect() } -pub fn compute_deposit_logs_hash(deposit_log_hashes: Vec) -> Result { - if deposit_log_hashes.is_empty() { +pub fn compute_privileged_transactions_hash( + privileged_transaction_hashes: Vec, +) -> Result { + if privileged_transaction_hashes.is_empty() { return Ok(H256::zero()); } - let deposit_hashes_len: u16 = deposit_log_hashes.len().try_into()?; + let privileged_transaction_hashes_len: u16 = privileged_transaction_hashes.len().try_into()?; Ok(H256::from_slice( [ - &deposit_hashes_len.to_be_bytes(), + &privileged_transaction_hashes_len.to_be_bytes(), keccak( - deposit_log_hashes + privileged_transaction_hashes .iter() .map(H256::as_bytes) .collect::>() @@ -55,7 +57,7 @@ pub fn compute_deposit_logs_hash(deposit_log_hashes: Vec) -> Result, pub l1_messages: Vec, - pub deposit_logs: Vec, + pub privileged_transactions: Vec, } impl TryFrom for AccountStateDiffType { @@ -127,7 +127,7 @@ impl Default for StateDiff { last_header: BlockHeader::default(), modified_accounts: BTreeMap::new(), l1_messages: Vec::new(), - deposit_logs: Vec::new(), + privileged_transactions: Vec::new(), } } } @@ -177,11 +177,11 @@ impl StateDiff { encoded.extend(message_encoded); } - let deposits_len: u16 = self.deposit_logs.len().try_into()?; - encoded.extend(deposits_len.to_be_bytes()); - for deposit in self.deposit_logs.iter() { - let deposit_encoded = deposit.encode(); - encoded.extend(deposit_encoded); + let privileged_tx_len: u16 = self.privileged_transactions.len().try_into()?; + encoded.extend(privileged_tx_len.to_be_bytes()); + for privileged_tx in self.privileged_transactions.iter() { + let privileged_tx_encoded = privileged_tx.encode(); + encoded.extend(privileged_tx_encoded); } Ok(Bytes::from(encoded)) @@ -238,14 +238,14 @@ impl StateDiff { }); } - let deposit_logs_len = decoder.get_u16()?; + let privileged_transactions_len = decoder.get_u16()?; - let mut deposit_logs = Vec::with_capacity(deposit_logs_len.into()); - for _ in 0..deposit_logs_len { + let mut privileged_transactions = Vec::with_capacity(privileged_transactions_len.into()); + for _ in 0..privileged_transactions_len { let address = decoder.get_address()?; let amount = decoder.get_u256()?; - deposit_logs.push(DepositLog { + privileged_transactions.push(PrivilegedTransactionLog { address, amount, nonce: Default::default(), @@ -257,7 +257,7 @@ impl StateDiff { last_header, modified_accounts, l1_messages: l1messages, - deposit_logs, + privileged_transactions, }) } @@ -575,7 +575,7 @@ pub fn prepare_state_diff( last_header: BlockHeader, db: &impl VmDatabase, l1messages: &[L1Message], - deposits: &[PrivilegedL2Transaction], + privileged_transactions: &[PrivilegedL2Transaction], account_updates: Vec, ) -> Result { let mut modified_accounts = BTreeMap::new(); @@ -599,9 +599,9 @@ pub fn prepare_state_diff( version: StateDiff::default().version, last_header, l1_messages: l1messages.to_vec(), - deposit_logs: deposits + privileged_transactions: privileged_transactions .iter() - .map(|tx| DepositLog { + .map(|tx| PrivilegedTransactionLog { address: match tx.to { TxKind::Call(address) => address, TxKind::Create => Address::zero(), diff --git a/crates/l2/contracts/src/l1/CommonBridge.sol b/crates/l2/contracts/src/l1/CommonBridge.sol index 41874266d7..b99cb82162 100644 --- a/crates/l2/contracts/src/l1/CommonBridge.sol +++ b/crates/l2/contracts/src/l1/CommonBridge.sol @@ -39,8 +39,8 @@ contract CommonBridge is /// that the logs were published on L1, and that that batch was committed. mapping(uint256 => bytes32) public batchWithdrawalLogsMerkleRoots; - /// @notice Array of hashed pending deposit logs. - bytes32[] public pendingDepositLogs; + /// @notice Array of hashed pending privileged transactions + bytes32[] public pendingTxHashes; address public ON_CHAIN_PROPOSER; @@ -48,9 +48,9 @@ contract CommonBridge is /// @dev Used by the L1Watcher to fetch logs starting from this block. uint256 public lastFetchedL1Block; - /// @notice Global deposit identifier, it is incremented each time a new deposit is made. + /// @notice Global privileged transaction identifier, it is incremented each time a new privileged transaction is made. /// @dev It is used as the nonce of the mint transaction created by the L1Watcher. - uint256 public depositId; + uint256 public transactionId; /// @notice Address of the bridge on the L2 /// @dev It's used to validate withdrawals @@ -97,15 +97,19 @@ contract CommonBridge is ON_CHAIN_PROPOSER = onChainProposer; lastFetchedL1Block = block.number; - depositId = 0; + transactionId = 0; OwnableUpgradeable.__Ownable_init(owner); ReentrancyGuardUpgradeable.__ReentrancyGuard_init(); } /// @inheritdoc ICommonBridge - function getPendingDepositLogs() public view returns (bytes32[] memory) { - return pendingDepositLogs; + function getPendingTransactionHashes() + public + view + returns (bytes32[] memory) + { + return pendingTxHashes; } /// Burns at least {amount} gas @@ -119,27 +123,26 @@ contract CommonBridge is bytes32 l2MintTxHash = keccak256( bytes.concat( + bytes20(from), bytes20(sendValues.to), + bytes32(transactionId), bytes32(sendValues.value), - bytes32(depositId), - bytes20(from), bytes32(sendValues.gasLimit), bytes32(keccak256(sendValues.data)) ) ); - pendingDepositLogs.push(l2MintTxHash); + pendingTxHashes.push(l2MintTxHash); - emit L1ToL2Message( - sendValues.value, - sendValues.to, - depositId, + emit PrivilegedTxSent( from, + sendValues.to, + transactionId, + sendValues.value, sendValues.gasLimit, - sendValues.data, - l2MintTxHash + sendValues.data ); - depositId += 1; + transactionId += 1; } /// @inheritdoc ICommonBridge @@ -195,40 +198,40 @@ contract CommonBridge is } /// @inheritdoc ICommonBridge - function getPendingDepositLogsVersionedHash( + function getPendingTransactionsVersionedHash( uint16 number ) public view returns (bytes32) { require(number > 0, "CommonBridge: number is zero (get)"); require( - uint256(number) <= pendingDepositLogs.length, - "CommonBridge: number is greater than the length of depositLogs (get)" + uint256(number) <= pendingTxHashes.length, + "CommonBridge: number is greater than the length of pendingTxHashes (get)" ); - bytes memory logs; + bytes memory hashes; for (uint i = 0; i < number; i++) { - logs = bytes.concat(logs, pendingDepositLogs[i]); + hashes = bytes.concat(hashes, pendingTxHashes[i]); } return bytes32(bytes2(number)) | - bytes32(uint256(uint240(uint256(keccak256(logs))))); + bytes32(uint256(uint240(uint256(keccak256(hashes))))); } /// @inheritdoc ICommonBridge - function removePendingDepositLogs( + function removePendingTransactionHashes( uint16 number ) public onlyOnChainProposer { require( - number <= pendingDepositLogs.length, - "CommonBridge: number is greater than the length of depositLogs (remove)" + number <= pendingTxHashes.length, + "CommonBridge: number is greater than the length of pendingTxHashes (remove)" ); - for (uint i = 0; i < pendingDepositLogs.length - number; i++) { - pendingDepositLogs[i] = pendingDepositLogs[i + number]; + for (uint i = 0; i < pendingTxHashes.length - number; i++) { + pendingTxHashes[i] = pendingTxHashes[i + number]; } for (uint _i = 0; _i < number; _i++) { - pendingDepositLogs.pop(); + pendingTxHashes.pop(); } } diff --git a/crates/l2/contracts/src/l1/OnChainProposer.sol b/crates/l2/contracts/src/l1/OnChainProposer.sol index c6159d97ae..27dd60b1b7 100644 --- a/crates/l2/contracts/src/l1/OnChainProposer.sol +++ b/crates/l2/contracts/src/l1/OnChainProposer.sol @@ -23,16 +23,16 @@ contract OnChainProposer is { /// @notice Committed batches data. /// @dev This struct holds the information about the committed batches. - /// @dev processedDepositLogsRollingHash is the Merkle root of the logs of the - /// deposits that were processed in the batch being committed. The amount of - /// logs that is encoded in this root are to be removed from the - /// pendingDepositLogs queue of the CommonBridge contract. + /// @dev processedPrivilegedTransactionsRollingHash is the Merkle root of the hashes of the + /// privileged transactions that were processed in the batch being committed. The amount of + /// hashes that are encoded in this root are to be removed from the + /// pendingTxHashes queue of the CommonBridge contract. /// @dev withdrawalsLogsMerkleRoot is the Merkle root of the Merkle tree containing /// all the withdrawals that were processed in the batch being committed struct BatchCommitmentInfo { bytes32 newStateRoot; bytes32 stateDiffKZGVersionedHash; - bytes32 processedDepositLogsRollingHash; + bytes32 processedPrivilegedTransactionsRollingHash; bytes32 withdrawalsLogsMerkleRoot; bytes32 lastBlockHash; } @@ -174,7 +174,7 @@ contract OnChainProposer is uint256 batchNumber, bytes32 newStateRoot, bytes32 withdrawalsLogsMerkleRoot, - bytes32 processedDepositLogsRollingHash, + bytes32 processedPrivilegedTransactionsRollingHash, bytes32 lastBlockHash ) external override onlySequencer whenNotPaused { // TODO: Refactor validation @@ -191,14 +191,15 @@ contract OnChainProposer is "OnChainProposer: lastBlockHash cannot be zero" ); - if (processedDepositLogsRollingHash != bytes32(0)) { - bytes32 claimedProcessedDepositLogs = ICommonBridge(BRIDGE) - .getPendingDepositLogsVersionedHash( - uint16(bytes2(processedDepositLogsRollingHash)) + if (processedPrivilegedTransactionsRollingHash != bytes32(0)) { + bytes32 claimedProcessedTransactions = ICommonBridge(BRIDGE) + .getPendingTransactionsVersionedHash( + uint16(bytes2(processedPrivilegedTransactionsRollingHash)) ); require( - claimedProcessedDepositLogs == processedDepositLogsRollingHash, - "OnChainProposer: invalid deposit logs" + claimedProcessedTransactions == + processedPrivilegedTransactionsRollingHash, + "OnChainProposer: invalid privileged transaction logs" ); } if (withdrawalsLogsMerkleRoot != bytes32(0)) { @@ -225,7 +226,7 @@ contract OnChainProposer is batchCommitments[batchNumber] = BatchCommitmentInfo( newStateRoot, blobVersionedHash, - processedDepositLogsRollingHash, + processedPrivilegedTransactionsRollingHash, withdrawalsLogsMerkleRoot, lastBlockHash ); @@ -296,14 +297,17 @@ contract OnChainProposer is } lastVerifiedBatch = batchNumber; - // The first 2 bytes are the number of deposits. - uint16 deposits_amount = uint16( + // The first 2 bytes are the number of privileged transactions. + uint16 privileged_transaction_count = uint16( bytes2( - batchCommitments[batchNumber].processedDepositLogsRollingHash + batchCommitments[batchNumber] + .processedPrivilegedTransactionsRollingHash ) ); - if (deposits_amount > 0) { - ICommonBridge(BRIDGE).removePendingDepositLogs(deposits_amount); + if (privileged_transaction_count > 0) { + ICommonBridge(BRIDGE).removePendingTransactionHashes( + privileged_transaction_count + ); } // Remove previous batch commitment as it is no longer needed. @@ -354,22 +358,23 @@ contract OnChainProposer is callResult, "OnChainProposer: call to ALIGNEDPROOFAGGREGATOR failed" ); - bool proofVerified = abi.decode(response, (bool)); require( proofVerified, "OnChainProposer: Aligned proof verification failed" ); - // The first 2 bytes are the number of deposits. - uint16 deposits_amount = uint16( + // The first 2 bytes are the number of transactions. + uint16 privileged_transaction_count = uint16( bytes2( batchCommitments[batchNumber] - .processedDepositLogsRollingHash + .processedPrivilegedTransactionsRollingHash ) ); - if (deposits_amount > 0) { - ICommonBridge(BRIDGE).removePendingDepositLogs(deposits_amount); + if (privileged_transaction_count > 0) { + ICommonBridge(BRIDGE).removePendingTransactionHashes( + privileged_transaction_count + ); } // Remove previous batch commitment @@ -407,11 +412,12 @@ contract OnChainProposer is withdrawalsMerkleRoot, "OnChainProposer: withdrawals public inputs don't match with committed withdrawals" ); - bytes32 depositsLogHash = bytes32(publicData[96:128]); + bytes32 privilegedTransactionsHash = bytes32(publicData[96:128]); require( - batchCommitments[batchNumber].processedDepositLogsRollingHash == - depositsLogHash, - "OnChainProposer: deposits hash public input does not match with committed deposits" + batchCommitments[batchNumber] + .processedPrivilegedTransactionsRollingHash == + privilegedTransactionsHash, + "OnChainProposer: privileged transactions hash public input does not match with committed transactions" ); bytes32 blobVersionedHash = bytes32(publicData[128:160]); require( diff --git a/crates/l2/contracts/src/l1/based/OnChainProposer.sol b/crates/l2/contracts/src/l1/based/OnChainProposer.sol index be2f6552dc..d79c6d88ea 100644 --- a/crates/l2/contracts/src/l1/based/OnChainProposer.sol +++ b/crates/l2/contracts/src/l1/based/OnChainProposer.sol @@ -22,16 +22,16 @@ contract OnChainProposer is { /// @notice Committed batches data. /// @dev This struct holds the information about the committed batches. - /// @dev processedDepositLogsRollingHash is the Merkle root of the logs of the - /// deposits that were processed in the batch being committed. The amount of - /// logs that is encoded in this root are to be removed from the - /// pendingDepositLogs queue of the CommonBridge contract. + /// @dev processedPrivilegedTransactionsRollingHash is the Merkle root of the hashes of the + /// privileged transactions that were processed in the batch being committed. The amount of + /// hashes that are encoded in this root are to be removed from the + /// pendingTxHashes queue of the CommonBridge contract. /// @dev withdrawalsLogsMerkleRoot is the Merkle root of the Merkle tree containing /// all the withdrawals that were processed in the batch being committed struct BatchCommitmentInfo { bytes32 newStateRoot; bytes32 blobVersionedHash; - bytes32 processedDepositLogsRollingHash; + bytes32 processedPrivilegedTransactionsRollingHash; bytes32 withdrawalsLogsMerkleRoot; bytes32 lastBlockHash; } @@ -226,7 +226,7 @@ contract OnChainProposer is uint256 batchNumber, bytes32 newStateRoot, bytes32 withdrawalsLogsMerkleRoot, - bytes32 processedDepositLogsRollingHash, + bytes32 processedPrivilegedTransactionsRollingHash, bytes32 lastBlockHash, bytes[] calldata //rlpEncodedBlocks ) external override onlyLeaderSequencer { @@ -246,14 +246,15 @@ contract OnChainProposer is // Check if commitment is equivalent to blob's KZG commitment. - if (processedDepositLogsRollingHash != bytes32(0)) { - bytes32 claimedProcessedDepositLogs = ICommonBridge(BRIDGE) - .getPendingDepositLogsVersionedHash( - uint16(bytes2(processedDepositLogsRollingHash)) + if (processedPrivilegedTransactionsRollingHash != bytes32(0)) { + bytes32 claimedProcessedTransactions = ICommonBridge(BRIDGE) + .getPendingTransactionsVersionedHash( + uint16(bytes2(processedPrivilegedTransactionsRollingHash)) ); require( - claimedProcessedDepositLogs == processedDepositLogsRollingHash, - "OnChainProposer: invalid deposit logs" + claimedProcessedTransactions == + processedPrivilegedTransactionsRollingHash, + "OnChainProposer: invalid privileged transactions log" ); } if (withdrawalsLogsMerkleRoot != bytes32(0)) { @@ -280,7 +281,7 @@ contract OnChainProposer is batchCommitments[batchNumber] = BatchCommitmentInfo( newStateRoot, blobVersionedHash, - processedDepositLogsRollingHash, + processedPrivilegedTransactionsRollingHash, withdrawalsLogsMerkleRoot, lastBlockHash ); @@ -347,14 +348,17 @@ contract OnChainProposer is } lastVerifiedBatch = batchNumber; - // The first 2 bytes are the number of deposits. - uint16 deposits_amount = uint16( + // The first 2 bytes are the number of privileged transactions. + uint16 privileged_transaction_count = uint16( bytes2( - batchCommitments[batchNumber].processedDepositLogsRollingHash + batchCommitments[batchNumber] + .processedPrivilegedTransactionsRollingHash ) ); - if (deposits_amount > 0) { - ICommonBridge(BRIDGE).removePendingDepositLogs(deposits_amount); + if (privileged_transaction_count > 0) { + ICommonBridge(BRIDGE).removePendingTransactionHashes( + privileged_transaction_count + ); } // Remove previous batch commitment as it is no longer needed. @@ -405,22 +409,23 @@ contract OnChainProposer is callResult, "OnChainProposer: call to ALIGNEDPROOFAGGREGATOR failed" ); - bool proofVerified = abi.decode(response, (bool)); require( proofVerified, "OnChainProposer: Aligned proof verification failed" ); - // The first 2 bytes are the number of deposits. - uint16 deposits_amount = uint16( + // The first 2 bytes are the number of privileged transactions. + uint16 transaction_count = uint16( bytes2( batchCommitments[batchNumber] - .processedDepositLogsRollingHash + .processedPrivilegedTransactionsRollingHash ) ); - if (deposits_amount > 0) { - ICommonBridge(BRIDGE).removePendingDepositLogs(deposits_amount); + if (transaction_count > 0) { + ICommonBridge(BRIDGE).removePendingTransactionHashes( + transaction_count + ); } // Remove previous batch commitment @@ -458,11 +463,12 @@ contract OnChainProposer is withdrawalsMerkleRoot, "OnChainProposer: withdrawals public inputs don't match with committed withdrawals" ); - bytes32 depositsLogHash = bytes32(publicData[96:128]); + bytes32 privilegedTransactionsHash = bytes32(publicData[96:128]); require( - batchCommitments[batchNumber].processedDepositLogsRollingHash == - depositsLogHash, - "OnChainProposer: deposits hash public input does not match with committed deposits" + batchCommitments[batchNumber] + .processedPrivilegedTransactionsRollingHash == + privilegedTransactionsHash, + "OnChainProposer: privileged transaction hash public input does not match with committed transactions" ); bytes32 lastBlockHash = bytes32(publicData[128:160]); require( diff --git a/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol b/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol index 0e01e121af..878791c688 100644 --- a/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol +++ b/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol @@ -6,26 +6,21 @@ pragma solidity =0.8.29; /// @notice A CommonBridge contract is a contract that allows L1<->L2 communication /// from L1. It both sends messages from L1 to L2 and receives messages from L2. interface ICommonBridge { - /// @notice A deposit to L2 has initiated. - /// @dev Event emitted when a deposit is initiated. - /// @param amount the amount of tokens being deposited. - /// @param to the address that will be called in the L2. - /// @param depositId Id used to differentiate deposits with same amount and recipient. - /// @param from the address that initiated the deposit. + /// @notice A privileged transaction to L2 has initiated. + /// @dev Event emitted when a privileged transaction is initiated. + /// @param from the address that initiated the transaction. + /// @param to the recipient on L2 + /// @param transactionId Id used to make transactions unique + /// @param value the value of the transaction /// @param gasLimit the gas limit for the deposit transaction. /// @param data The calldata of the deposit transaction. - /// @param l2MintTxHash the hash of the transaction that will finalize the - /// deposit in L2. Could be used to track the status of the deposit finalization - /// on L2. You can use this hash to retrive the tx data. - /// It is the result of keccak(abi.encode(transaction)). - event L1ToL2Message( - uint256 indexed amount, + event PrivilegedTxSent ( + address indexed from, address indexed to, - uint256 indexed depositId, - address from, + uint256 indexed transactionId, + uint256 value, uint256 gasLimit, - bytes data, - bytes32 l2MintTxHash + bytes data ); /// @notice L2 withdrawals have been published on L1. @@ -49,10 +44,10 @@ interface ICommonBridge { bytes data; } - /// @notice Method to retrieve all the pending deposit logs hashes. - /// @dev This method is used by the L2 L1_Watcher to get the pending deposit - /// logs to be processed. - function getPendingDepositLogs() external view returns (bytes32[] memory); + /// @notice Method to retrieve all the pending transaction hashes. + /// @dev This method is used by the L2 L1_Watcher to get the pending + /// privileged transactions to be processed. + function getPendingTransactionHashes() external view returns (bytes32[] memory); /// @notice Method that sends a transaction to L2. /// @dev The deposit process starts here by emitting a L1ToL2Message @@ -69,19 +64,19 @@ interface ICommonBridge { function deposit(address l2Recipient) external payable; /// @notice Method to retrieve the versioned hash of the first `number` - /// pending deposit logs. - /// @param number of pending deposit logs to retrieve the versioned hash. - function getPendingDepositLogsVersionedHash( + /// pending privileged transactions. + /// @param number of pending privileged transaction to retrieve the versioned hash. + function getPendingTransactionsVersionedHash( uint16 number ) external view returns (bytes32); - /// @notice Remove pending deposit from the pendingDepositLogs queue. + /// @notice Remove pending transaction hashes from the queue. /// @dev This method is used by the L2 OnChainOperator to remove the pending - /// deposit logs from the queue after the deposit is verified. - /// @param number of pending deposit logs to remove. - /// As deposits are processed in order, we don't need to specify - /// the pending deposit logs to remove, only the number of them. - function removePendingDepositLogs(uint16 number) external; + /// privileged transactions from the queue after the transaction is included. + /// @param number of pending transaction hashes to remove. + /// As transactions are processed in order, we don't need to specify + /// the transaction hashes to remove, only the number of them. + function removePendingTransactionHashes(uint16 number) external; /// @notice Method to retrieve the merkle root of the withdrawal logs of a /// given block. diff --git a/crates/l2/contracts/src/l1/interfaces/IOnChainProposer.sol b/crates/l2/contracts/src/l1/interfaces/IOnChainProposer.sol index 8171fcb2ab..d76bb74c05 100644 --- a/crates/l2/contracts/src/l1/interfaces/IOnChainProposer.sol +++ b/crates/l2/contracts/src/l1/interfaces/IOnChainProposer.sol @@ -41,14 +41,14 @@ interface IOnChainProposer { /// @param newStateRoot the new state root of the batch to be committed. /// @param withdrawalsLogsMerkleRoot the merkle root of the withdrawal logs /// of the batch to be committed. - /// @param processedDepositLogsRollingHash the rolling hash of the processed - /// deposits logs of the batch to be committed. + /// @param processedPrivilegedTransactionsRollingHash the rolling hash of the processed + /// privileged transactions of the batch to be committed. /// @param lastBlockHash the hash of the last block of the batch to be committed. function commitBatch( uint256 batchNumber, bytes32 newStateRoot, bytes32 withdrawalsLogsMerkleRoot, - bytes32 processedDepositLogsRollingHash, + bytes32 processedPrivilegedTransactionsRollingHash, bytes32 lastBlockHash ) external; diff --git a/crates/l2/prover/zkvm/interface/src/execution.rs b/crates/l2/prover/zkvm/interface/src/execution.rs index b13fd816c6..7a31360705 100644 --- a/crates/l2/prover/zkvm/interface/src/execution.rs +++ b/crates/l2/prover/zkvm/interface/src/execution.rs @@ -23,8 +23,11 @@ use ethrex_common::types::{ kzg_commitment_to_versioned_hash, }; use ethrex_l2_common::{ - deposits::{DepositError, compute_deposit_logs_hash, get_block_deposits}, l1_messages::get_block_l1_messages, + privileged_transactions::{ + PrivilegedTransactionError, compute_privileged_transactions_hash, + get_block_privileged_transactions, + }, state_diff::{StateDiff, StateDiffError, prepare_state_diff}, }; #[cfg(feature = "l2")] @@ -45,8 +48,8 @@ pub enum StatelessExecutionError { #[error("EVM error: {0}")] EvmError(#[from] EvmError), #[cfg(feature = "l2")] - #[error("Deposit calculation error: {0}")] - DepositError(#[from] DepositError), + #[error("Privileged Transaction calculation error: {0}")] + PrivilegedTransactionError(#[from] PrivilegedTransactionError), #[cfg(feature = "l2")] #[error("State diff error: {0}")] StateDiffError(#[from] StateDiffError), @@ -70,8 +73,8 @@ pub enum StatelessExecutionError { InvalidInitialStateTrie, #[error("Invalid final state trie")] InvalidFinalStateTrie, - #[error("Missing deposit hash")] - MissingDepositHash, + #[error("Missing privileged transaction hash")] + MissingPrivilegedTransactionHash, #[error("Failed to apply account updates {0}")] ApplyAccountUpdates(String), #[error("No block headers required, should at least require parent header")] @@ -82,8 +85,8 @@ pub enum StatelessExecutionError { InvalidBlockHash(u64), #[error("Invalid parent block header")] InvalidParentBlockHeader, - #[error("Failed to calculate deposit hash")] - InvalidDeposit, + #[error("Failed to calculate privileged transaction hash")] + InvalidPrivilegedTransaction, #[error("Internal error: {0}")] Internal(String), } @@ -136,7 +139,7 @@ pub fn stateless_validation_l1( #[cfg(feature = "l2")] l1messages_merkle_root: H256::zero(), #[cfg(feature = "l2")] - deposit_logs_hash: H256::zero(), + privileged_transactions_hash: H256::zero(), #[cfg(feature = "l2")] blob_versioned_hash: H256::zero(), last_block_hash, @@ -162,9 +165,13 @@ pub fn stateless_validation_l2( last_block_hash, } = execute_stateless(blocks, db, elasticity_multiplier)?; - let (l1messages, deposits) = get_batch_l1messages_and_deposits(blocks, &receipts)?; - let (l1messages_merkle_root, deposit_logs_hash) = - compute_l1messages_and_deposits_digests(&l1messages, &deposits)?; + let (l1messages, privileged_transactions) = + get_batch_l1messages_and_privileged_transactions(blocks, &receipts)?; + let (l1messages_merkle_root, privileged_transactions_hash) = + compute_l1messages_and_privileged_transactions_digests( + &l1messages, + &privileged_transactions, + )?; // TODO: this could be replaced with something like a ProverConfig in the future. let validium = (blob_commitment, blob_proof) == ([0; 48], [0; 48]); @@ -178,7 +185,7 @@ pub fn stateless_validation_l2( last_block_header, &initial_db, &l1messages, - &deposits, + &privileged_transactions, account_updates.values().cloned().collect(), )?; verify_blob(state_diff, blob_commitment, blob_proof)? @@ -190,7 +197,7 @@ pub fn stateless_validation_l2( initial_state_hash, final_state_hash, l1messages_merkle_root, - deposit_logs_hash, + privileged_transactions_hash, blob_versioned_hash, last_block_hash, }) @@ -292,7 +299,7 @@ fn execute_stateless( .map_err(StatelessExecutionError::GasValidationError)?; validate_receipts_root(&block.header, &receipts) .map_err(StatelessExecutionError::ReceiptsRootValidationError)?; - // validate_requests_hash doesn't do anything for l2 blocks as this verifies l1 requests (messages, deposits and consolidations) + // validate_requests_hash doesn't do anything for l2 blocks as this verifies l1 requests (messages, privileged transactions and consolidations) validate_requests_hash(&block.header, &db.chain_config, &result.requests) .map_err(StatelessExecutionError::RequestsRootValidationError)?; parent_block_header = &block.header; @@ -324,41 +331,42 @@ fn execute_stateless( } #[cfg(feature = "l2")] -fn get_batch_l1messages_and_deposits( +fn get_batch_l1messages_and_privileged_transactions( blocks: &[Block], receipts: &[Vec], ) -> Result<(Vec, Vec), StatelessExecutionError> { let mut l1messages = vec![]; - let mut deposits = vec![]; + let mut privileged_transactions = vec![]; for (block, receipts) in blocks.iter().zip(receipts) { let txs = &block.body.transactions; - deposits.extend(get_block_deposits(txs)); + privileged_transactions.extend(get_block_privileged_transactions(txs)); l1messages.extend(get_block_l1_messages(txs, receipts)); } - Ok((l1messages, deposits)) + Ok((l1messages, privileged_transactions)) } #[cfg(feature = "l2")] -fn compute_l1messages_and_deposits_digests( +fn compute_l1messages_and_privileged_transactions_digests( l1messages: &[L1Message], - deposits: &[PrivilegedL2Transaction], + privileged_transactions: &[PrivilegedL2Transaction], ) -> Result<(H256, H256), StatelessExecutionError> { use ethrex_l2_common::{l1_messages::get_l1_message_hash, merkle_tree::compute_merkle_root}; let message_hashes: Vec<_> = l1messages.iter().map(get_l1_message_hash).collect(); - let deposit_hashes: Vec<_> = deposits + let privileged_transactions_hashes: Vec<_> = privileged_transactions .iter() - .map(PrivilegedL2Transaction::get_deposit_hash) - .map(|hash| hash.ok_or(StatelessExecutionError::InvalidDeposit)) + .map(PrivilegedL2Transaction::get_privileged_hash) + .map(|hash| hash.ok_or(StatelessExecutionError::InvalidPrivilegedTransaction)) .collect::>()?; let l1message_merkle_root = compute_merkle_root(&message_hashes); - let deposit_logs_hash = - compute_deposit_logs_hash(deposit_hashes).map_err(StatelessExecutionError::DepositError)?; + let privileged_transactions_hash = + compute_privileged_transactions_hash(privileged_transactions_hashes) + .map_err(StatelessExecutionError::PrivilegedTransactionError)?; - Ok((l1message_merkle_root, deposit_logs_hash)) + Ok((l1message_merkle_root, privileged_transactions_hash)) } #[cfg(feature = "l2")] diff --git a/crates/l2/prover/zkvm/interface/src/io.rs b/crates/l2/prover/zkvm/interface/src/io.rs index 6594bbea2a..a65a304d79 100644 --- a/crates/l2/prover/zkvm/interface/src/io.rs +++ b/crates/l2/prover/zkvm/interface/src/io.rs @@ -83,8 +83,8 @@ pub struct ProgramOutput { /// merkle root of all messages in a batch pub l1messages_merkle_root: H256, #[cfg(feature = "l2")] - /// hash of all the deposit logs made in a batch - pub deposit_logs_hash: H256, + /// hash of all the privileged transactions made in a batch + pub privileged_transactions_hash: H256, #[cfg(feature = "l2")] /// blob commitment versioned hash pub blob_versioned_hash: H256, @@ -100,7 +100,7 @@ impl ProgramOutput { #[cfg(feature = "l2")] self.l1messages_merkle_root.to_fixed_bytes(), #[cfg(feature = "l2")] - self.deposit_logs_hash.to_fixed_bytes(), + self.privileged_transactions_hash.to_fixed_bytes(), #[cfg(feature = "l2")] self.blob_versioned_hash.to_fixed_bytes(), self.last_block_hash.to_fixed_bytes(), diff --git a/crates/l2/sequencer/block_producer/payload_builder.rs b/crates/l2/sequencer/block_producer/payload_builder.rs index a688eaa63d..f73b12c293 100644 --- a/crates/l2/sequencer/block_producer/payload_builder.rs +++ b/crates/l2/sequencer/block_producer/payload_builder.rs @@ -13,7 +13,7 @@ use ethrex_common::{ }; use ethrex_l2_common::l1_messages::get_block_l1_messages; use ethrex_l2_common::state_diff::{ - AccountStateDiff, BLOCK_HEADER_LEN, DEPOSITS_LOG_LEN, L1MESSAGE_LOG_LEN, + AccountStateDiff, BLOCK_HEADER_LEN, L1MESSAGE_LOG_LEN, PRIVILEGED_TX_LOG_LEN, SIMPLE_TX_STATE_DIFF_SIZE, StateDiffError, }; use ethrex_metrics::metrics; @@ -95,7 +95,7 @@ pub async fn fill_transactions( context: &mut PayloadBuildContext, store: &Store, ) -> Result<(), BlockProducerError> { - // version (u8) + header fields (struct) + messages_len (u16) + deposits_len (u16) + accounts_diffs_len (u16) + // version (u8) + header fields (struct) + messages_len (u16) + privileged_tx_len (u16) + accounts_diffs_len (u16) let mut acc_size_without_accounts = 1 + *BLOCK_HEADER_LEN + 2 + 2 + 2; let mut size_accounts_diffs = 0; let mut account_diffs = HashMap::new(); @@ -183,7 +183,7 @@ pub async fn fill_transactions( &merged_diffs, &head_tx, &receipt, - *DEPOSITS_LOG_LEN, + *PRIVILEGED_TX_LOG_LEN, *L1MESSAGE_LOG_LEN, )?; @@ -206,7 +206,7 @@ pub async fn fill_transactions( // Pull transaction from the mempool blockchain.remove_transaction_from_pool(&head_tx.tx.compute_hash())?; - // We only add the messages and deposits length because the accounts diffs may change + // We only add the messages and privileged transaction length because the accounts diffs may change acc_size_without_accounts += tx_size_without_accounts; size_accounts_diffs = new_accounts_diff_size; // Include the new accounts diffs @@ -367,7 +367,7 @@ fn merge_diffs( } /// Calculates the size of the state diffs introduced by the transaction, including -/// the size of messages and deposits logs for this transaction, and the total +/// the size of messages and privileged transactions, and the total /// size of all account diffs accumulated so far in the block. /// This is necessary because each transaction can modify accounts that were already /// changed by previous transactions, so we must recalculate the total diff size each time. @@ -375,7 +375,7 @@ fn calculate_tx_diff_size( merged_diffs: &HashMap, head_tx: &HeadTransaction, receipt: &Receipt, - deposits_log_len: usize, + privileged_tx_log_len: usize, messages_log_len: usize, ) -> Result<(usize, usize), BlockProducerError> { let mut tx_state_diff_size = 0; @@ -396,8 +396,8 @@ fn calculate_tx_diff_size( new_accounts_diff_size += encoded.len(); } - if is_deposit_l2(head_tx) { - tx_state_diff_size += deposits_log_len; + if is_privileged_tx(head_tx) { + tx_state_diff_size += privileged_tx_log_len; } tx_state_diff_size += get_block_l1_messages(&[Transaction::from(head_tx.clone())], &[receipt.clone()]).len() @@ -406,6 +406,6 @@ fn calculate_tx_diff_size( Ok((tx_state_diff_size, new_accounts_diff_size)) } -fn is_deposit_l2(tx: &Transaction) -> bool { +fn is_privileged_tx(tx: &Transaction) -> bool { matches!(tx, Transaction::PrivilegedL2Transaction(_tx)) } diff --git a/crates/l2/sequencer/errors.rs b/crates/l2/sequencer/errors.rs index eb2f23efc1..c4f772250d 100644 --- a/crates/l2/sequencer/errors.rs +++ b/crates/l2/sequencer/errors.rs @@ -4,7 +4,7 @@ use crate::utils::error::UtilsError; use ethereum_types::FromStrRadixErr; use ethrex_blockchain::error::{ChainError, InvalidForkChoice}; use ethrex_common::types::{BlobsBundleError, FakeExponentialError}; -use ethrex_l2_common::deposits::DepositError; +use ethrex_l2_common::privileged_transactions::PrivilegedTransactionError; use ethrex_l2_common::prover::ProverType; use ethrex_l2_common::state_diff::StateDiffError; use ethrex_rpc::clients::EngineClientError; @@ -233,8 +233,8 @@ pub enum CommitterError { InternalError(String), #[error("Failed to get withdrawals: {0}")] FailedToGetWithdrawals(#[from] UtilsError), - #[error("Deposit error: {0}")] - DepositError(#[from] DepositError), + #[error("Privileged Transaction error: {0}")] + PrivilegedTransactionError(#[from] PrivilegedTransactionError), #[error("Spawned GenServer Error")] GenServerError(GenServerError), } diff --git a/crates/l2/sequencer/l1_committer.rs b/crates/l2/sequencer/l1_committer.rs index 34f3672942..34df169c22 100644 --- a/crates/l2/sequencer/l1_committer.rs +++ b/crates/l2/sequencer/l1_committer.rs @@ -15,9 +15,11 @@ use ethrex_common::{ }; use ethrex_l2_common::{ calldata::Value, - deposits::{compute_deposit_logs_hash, get_block_deposits}, l1_messages::{get_block_l1_messages, get_l1_message_hash}, merkle_tree::compute_merkle_root, + privileged_transactions::{ + compute_privileged_transactions_hash, get_block_privileged_transactions, + }, state_diff::{StateDiff, prepare_state_diff}, }; use ethrex_l2_sdk::calldata::encode_calldata; @@ -202,7 +204,7 @@ async fn commit_next_batch_to_l1(state: &mut CommitterState) -> Result<(), Commi blobs_bundle, new_state_root, message_hashes, - deposit_logs_hash, + privileged_transactions_hash, last_block_of_batch, ) = prepare_batch_from_block(state, *last_block).await?; @@ -216,7 +218,7 @@ async fn commit_next_batch_to_l1(state: &mut CommitterState) -> Result<(), Commi first_block: first_block_to_commit, last_block: last_block_of_batch, state_root: new_state_root, - deposit_logs_hash, + privileged_transactions_hash, message_hashes, blobs_bundle, commit_tx: None, @@ -285,10 +287,10 @@ async fn prepare_batch_from_block( let mut blobs_bundle = BlobsBundle::default(); let mut acc_messages = vec![]; - let mut acc_deposits = vec![]; + let mut acc_privileged_txs = vec![]; let mut acc_account_updates: HashMap = HashMap::new(); let mut message_hashes = vec![]; - let mut deposit_logs_hashes = vec![]; + let mut privileged_transactions_hashes = vec![]; let mut new_state_root = H256::default(); #[cfg(feature = "metrics")] @@ -339,9 +341,9 @@ async fn prepare_batch_from_block( .inspect_err(|_| tracing::error!("Failed to collect metric tx count")) .unwrap_or(0) ); - // Get block messages and deposits + // Get block messages and privileged transactions let messages = get_block_l1_messages(&txs, &receipts); - let deposits = get_block_deposits(&txs); + let privileged_transactions = get_block_privileged_transactions(&txs); // Get block account updates. let block_to_commit = Block::new(block_to_commit_header.clone(), block_to_commit_body); @@ -366,7 +368,7 @@ async fn prepare_batch_from_block( // Accumulate block data with the rest of the batch. acc_messages.extend(messages.clone()); - acc_deposits.extend(deposits.clone()); + acc_privileged_txs.extend(privileged_transactions.clone()); for account in account_updates { let address = account.address; if let Some(existing) = acc_account_updates.get_mut(&address) { @@ -391,7 +393,7 @@ async fn prepare_batch_from_block( block_to_commit_header, &parent_db, &acc_messages, - &acc_deposits, + &acc_privileged_txs, acc_account_updates.clone().into_values().collect(), )?; generate_blobs_bundle(&state_diff) @@ -411,10 +413,10 @@ async fn prepare_batch_from_block( blobs_bundle = bundle; _blob_size = latest_blob_size; - deposit_logs_hashes.extend( - deposits + privileged_transactions_hashes.extend( + privileged_transactions .iter() - .filter_map(|tx| tx.get_deposit_hash()) + .filter_map(|tx| tx.get_privileged_hash()) .collect::>(), ); @@ -429,13 +431,13 @@ async fn prepare_batch_from_block( last_added_block_number += 1; } - metrics!(if let (Ok(deposits_count), Ok(messages_count)) = ( - deposit_logs_hashes.len().try_into(), + metrics!(if let (Ok(privileged_transaction_count), Ok(messages_count)) = ( + privileged_transactions_hashes.len().try_into(), message_hashes.len().try_into() ) { let _ = state .rollup_store - .update_operations_count(tx_count, deposits_count, messages_count) + .update_operations_count(tx_count, privileged_transaction_count, messages_count) .await .inspect_err(|e| { tracing::error!("Failed to update operations metric: {}", e.to_string()) @@ -446,7 +448,8 @@ async fn prepare_batch_from_block( METRICS.set_blob_usage_percentage(blob_usage_percentage); ); - let deposit_logs_hash = compute_deposit_logs_hash(deposit_logs_hashes)?; + let privileged_transactions_hash = + compute_privileged_transactions_hash(privileged_transactions_hashes)?; for msg in &acc_messages { message_hashes.push(get_l1_message_hash(msg)); } @@ -454,7 +457,7 @@ async fn prepare_batch_from_block( blobs_bundle, new_state_root, message_hashes, - deposit_logs_hash, + privileged_transactions_hash, last_added_block_number, )) } @@ -486,7 +489,7 @@ async fn send_commitment( Value::Uint(U256::from(batch.number)), Value::FixedBytes(batch.state_root.0.to_vec().into()), Value::FixedBytes(messages_merkle_root.0.to_vec().into()), - Value::FixedBytes(batch.deposit_logs_hash.0.to_vec().into()), + Value::FixedBytes(batch.privileged_transactions_hash.0.to_vec().into()), Value::FixedBytes(last_block_hash.0.to_vec().into()), ]; diff --git a/crates/l2/sequencer/l1_watcher.rs b/crates/l2/sequencer/l1_watcher.rs index 4df05d3b3b..d941f56bc8 100644 --- a/crates/l2/sequencer/l1_watcher.rs +++ b/crates/l2/sequencer/l1_watcher.rs @@ -5,7 +5,9 @@ use crate::{sequencer::errors::L1WatcherError, utils::parse::hash_to_address}; use bytes::Bytes; use ethereum_types::{Address, H256, U256}; use ethrex_blockchain::Blockchain; +use ethrex_common::types::PrivilegedL2Transaction; use ethrex_common::{H160, types::Transaction}; +use ethrex_rpc::clients::EthClientError; use ethrex_rpc::types::receipt::RpcLog; use ethrex_rpc::{ clients::eth::{EthClient, eth_sender::Overrides}, @@ -135,22 +137,24 @@ impl GenServer for L1Watcher { } async fn watch(state: &mut L1WatcherState) { - let Ok(logs) = get_deposit_logs(state) + let Ok(logs) = get_privileged_transactions(state) .await .inspect_err(|err| error!("L1 Watcher Error: {err}")) else { return; }; - // We may not have a deposit nor a withdrawal, that means no events -> no logs. + // We may not have a privileged transaction nor a withdrawal, that means no events -> no logs. if !logs.is_empty() { - let _ = process_deposit_logs(state, logs) + let _ = process_privileged_transactions(state, logs) .await .inspect_err(|err| error!("L1 Watcher Error: {}", err)); }; } -pub async fn get_deposit_logs(state: &mut L1WatcherState) -> Result, L1WatcherError> { +pub async fn get_privileged_transactions( + state: &mut L1WatcherState, +) -> Result, L1WatcherError> { if state.last_block_fetched.is_zero() { state.last_block_fetched = state .eth_client @@ -165,7 +169,7 @@ pub async fn get_deposit_logs(state: &mut L1WatcherState) -> Result, .await? .checked_sub(state.l1_block_delay.into()) else { - warn!("Too close to genesis to request deposits"); + warn!("Too close to genesis to request privileged transactions"); return Ok(vec![]); }; @@ -192,8 +196,8 @@ pub async fn get_deposit_logs(state: &mut L1WatcherState) -> Result, state.last_block_fetched, new_last_block ); - // Matches the event L1ToL2Message from ICommonBridge.sol - let topic = keccak(b"L1ToL2Message(uint256,address,uint256,address,uint256,bytes,bytes32)"); + // Matches the event PrivilegedTxSent from ICommonBridge.sol + let topic = keccak(b"PrivilegedTxSent(address,address,uint256,uint256,uint256,bytes)"); let logs = state .eth_client @@ -214,33 +218,20 @@ pub async fn get_deposit_logs(state: &mut L1WatcherState) -> Result, debug!("Logs: {:#?}", logs); // If we have an error adding the tx to the mempool we may assign it to the next - // block to fetch, but we may lose a deposit tx. + // block to fetch, but we may lose a privileged tx. state.last_block_fetched = new_last_block; Ok(logs) } -pub async fn process_deposit_logs( +pub async fn process_privileged_transactions( state: &L1WatcherState, logs: Vec, ) -> Result, L1WatcherError> { - let mut deposit_txs = Vec::new(); + let mut privileged_txs = Vec::new(); for log in logs { - let deposit_data = DepositData::from_log(log.log)?; - - if deposit_already_processed(state, deposit_data.deposit_tx_hash).await? { - warn!( - "Deposit already processed (to: {:x}, value: {:x}, depositId: {:#}), skipping.", - deposit_data.to_address, deposit_data.value, deposit_data.deposit_id - ); - continue; - } - - info!( - "Initiating mint transaction for {:x} with value {:x} and depositId: {:#}", - deposit_data.to_address, deposit_data.value, deposit_data.deposit_id - ); + let privileged_transaction_data = PrivilegedTransactionData::from_log(log.log)?; let gas_price = state.l2_client.get_gas_price().await?; // Avoid panicking when using as_u64() @@ -248,41 +239,38 @@ pub async fn process_deposit_logs( .try_into() .map_err(|_| L1WatcherError::Custom("Failed at gas_price.try_into()".to_owned()))?; - let mint_transaction = state - .eth_client - .build_privileged_transaction( - deposit_data.to_address, - deposit_data.from, - Bytes::copy_from_slice(&deposit_data.calldata), - Overrides { - chain_id: Some( - state - .store - .get_chain_config() - .map_err(|e| { - L1WatcherError::FailedToRetrieveChainConfig(e.to_string()) - })? - .chain_id, - ), - // Using the deposit_id as nonce. - // If we make a transaction on the L2 with this address, we may break the - // deposit workflow. - nonce: Some(deposit_data.deposit_id.as_u64()), - value: Some(deposit_data.value), - gas_limit: Some(deposit_data.gas_limit.as_u64()), - // TODO(CHECK): Seems that when we start the L2, we need to set the gas. - // Otherwise, the transaction is not included in the mempool. - // We should override the blockchain to always include the transaction. - max_fee_per_gas: Some(gas_price), - max_priority_fee_per_gas: Some(gas_price), - ..Default::default() - }, - ) + let chain_id = state + .store + .get_chain_config() + .map_err(|e| L1WatcherError::FailedToRetrieveChainConfig(e.to_string()))? + .chain_id; + + let mint_transaction = privileged_transaction_data + .into_tx(&state.eth_client, chain_id, gas_price) .await?; + let tx = Transaction::PrivilegedL2Transaction(mint_transaction); + + if privileged_transaction_already_processed(state, tx.compute_hash()).await? { + warn!( + "Privileged transaction already processed (to: {:x}, value: {:x}, transactionId: {:#}), skipping.", + privileged_transaction_data.to_address, + privileged_transaction_data.value, + privileged_transaction_data.transaction_id + ); + continue; + } + + info!( + "Initiating mint transaction for {:x} with value {:x} and transactionId: {:#}", + privileged_transaction_data.to_address, + privileged_transaction_data.value, + privileged_transaction_data.transaction_id + ); + let Ok(hash) = state .blockchain - .add_transaction_to_pool(Transaction::PrivilegedL2Transaction(mint_transaction)) + .add_transaction_to_pool(tx) .await .inspect_err(|e| warn!("Failed to add mint transaction to the mempool: {e:#?}")) else { @@ -291,19 +279,19 @@ pub async fn process_deposit_logs( }; info!("Mint transaction added to mempool {hash:#x}",); - deposit_txs.push(hash); + privileged_txs.push(hash); } - Ok(deposit_txs) + Ok(privileged_txs) } -async fn deposit_already_processed( +async fn privileged_transaction_already_processed( state: &L1WatcherState, - deposit_hash: H256, + tx_hash: H256, ) -> Result { if state .store - .get_transaction_by_hash(deposit_hash) + .get_transaction_by_hash(tx_hash) .await .map_err(L1WatcherError::FailedAccessingStore)? .is_some() @@ -312,40 +300,34 @@ async fn deposit_already_processed( } // If we have a reconstructed state, we don't have the transaction in our store. - // Check if the deposit is marked as pending in the contract. - let pending_deposits = state + // Check if the transaction is marked as pending in the contract. + let pending_privileged_transactions = state .eth_client - .get_pending_deposit_logs(state.address) + .get_pending_privileged_transactions(state.address) .await?; - Ok(!pending_deposits.contains(&deposit_hash)) + Ok(!pending_privileged_transactions.contains(&tx_hash)) } -struct DepositData { +pub struct PrivilegedTransactionData { pub value: U256, pub to_address: H160, - pub deposit_id: U256, + pub transaction_id: U256, pub from: H160, pub gas_limit: U256, pub calldata: Vec, - pub deposit_tx_hash: H256, } -impl DepositData { - fn from_log(log: RpcLogInfo) -> Result { - let value = format!( - "{:#x}", - log.topics - .get(1) - .ok_or(L1WatcherError::FailedToDeserializeLog( - "Failed to parse mint value from log: log.topics[1] out of bounds".to_owned() - ))? - ) - .parse::() - .map_err(|e| { - L1WatcherError::FailedToDeserializeLog(format!( - "Failed to parse mint value from log: {e:#?}" - )) - })?; +impl PrivilegedTransactionData { + pub fn from_log(log: RpcLogInfo) -> Result { + let from = log + .topics + .get(1) + .ok_or(L1WatcherError::FailedToDeserializeLog( + "Failed to parse mint value from log: log.topics[1] out of bounds".to_owned(), + ))?; + + let from_address = hash_to_address(*from); + let to_address_hash = log .topics .get(2) @@ -354,31 +336,31 @@ impl DepositData { ))?; let to_address = hash_to_address(*to_address_hash); - let deposit_id = log + let transaction_id = log .topics .get(3) .ok_or(L1WatcherError::FailedToDeserializeLog( "Failed to parse beneficiary from log: log.topics[3] out of bounds".to_owned(), ))?; - let deposit_id = format!("{deposit_id:#x}").parse::().map_err(|e| { - L1WatcherError::FailedToDeserializeLog(format!( - "Failed to parse depositId value from log: {e:#?}" - )) - })?; + let transaction_id = format!("{transaction_id:#x}") + .parse::() + .map_err(|e| { + L1WatcherError::FailedToDeserializeLog(format!( + "Failed to parse transactionId value from log: {e:#?}" + )) + })?; // The previous values are indexed in the topic of the log. Data contains the rest. - // DATA = from: Address || gas_limit: uint256 || offset_calldata: uint256 || tx_hash: H256 || length_calldata: uint256 || calldata: bytes - // DATA = 0..32 || 32..64 || 64..96 || 96..128 || 128..160 || 160..(160+calldata_len) + // DATA = value: uint256 || gas_limit: uint256 || offset_calldata: uint256 || length_calldata: uint256 || calldata: bytes + // DATA = 0..32 || 32..64 || 64..96 || 96..128 || 128..(128+calldata_len) // Any value that is not 32 bytes is padded with zeros. - let from = log - .data - .get(12..32) - .ok_or(L1WatcherError::FailedToDeserializeLog( - "Failed to parse from from log: log.data[12..32] out of bounds".to_owned(), - ))?; - let from = Address::from_slice(from); + let value = U256::from_big_endian(log.data.get(0..32).ok_or( + L1WatcherError::FailedToDeserializeLog( + "Failed to parse gas_limit from log: log.data[32..64] out of bounds".to_owned(), + ), + )?); let gas_limit = U256::from_big_endian(log.data.get(32..64).ok_or( L1WatcherError::FailedToDeserializeLog( @@ -386,39 +368,55 @@ impl DepositData { ), )?); - let deposit_tx_hash = H256::from_slice( - log.data - .get(96..128) - .ok_or(L1WatcherError::FailedToDeserializeLog( - "Failed to parse deposit_tx_hash from log: log.data[96..128] out of bounds" - .to_owned(), - ))?, - ); - - let calldata_len = U256::from_big_endian( - log.data - .get(128..160) - .ok_or(L1WatcherError::FailedToDeserializeLog( - "Failed to parse calldata_len from log: log.data[128..160] out of bounds" - .to_owned(), - ))?, - ); + let calldata_len = U256::from_big_endian(log.data.get(96..128).ok_or( + L1WatcherError::FailedToDeserializeLog( + "Failed to parse calldata_len from log: log.data[96..128] out of bounds".to_owned(), + ), + )?); let calldata = log .data - .get(160..160 + calldata_len.as_usize()) + .get(128..128 + calldata_len.as_usize()) .ok_or(L1WatcherError::FailedToDeserializeLog( - "Failed to parse calldata from log: log.data[160..160 + calldata_len] out of bounds" + "Failed to parse calldata from log: log.data[128..128 + calldata_len] out of bounds" .to_owned(), ))?; Ok(Self { value, to_address, - deposit_id, - from, + transaction_id, + from: from_address, gas_limit, calldata: calldata.to_vec(), - deposit_tx_hash, }) } + pub async fn into_tx( + &self, + eth_client: &EthClient, + chain_id: u64, + gas_price: u64, + ) -> Result { + eth_client + .build_privileged_transaction( + self.to_address, + self.from, + Bytes::copy_from_slice(&self.calldata), + Overrides { + chain_id: Some(chain_id), + // Using the transaction_id as nonce. + // If we make a transaction on the L2 with this address, we may break the + // privileged transaction workflow. + nonce: Some(self.transaction_id.as_u64()), + value: Some(self.value), + gas_limit: Some(self.gas_limit.as_u64()), + // TODO(CHECK): Seems that when we start the L2, we need to set the gas. + // Otherwise, the transaction is not included in the mempool. + // We should override the blockchain to always include the transaction. + max_fee_per_gas: Some(gas_price), + max_priority_fee_per_gas: Some(gas_price), + ..Default::default() + }, + ) + .await + } } diff --git a/crates/l2/sequencer/metrics.rs b/crates/l2/sequencer/metrics.rs index 9bbfd3e8b1..25bdd46edd 100644 --- a/crates/l2/sequencer/metrics.rs +++ b/crates/l2/sequencer/metrics.rs @@ -131,12 +131,15 @@ async fn gather_metrics(state: &mut MetricsGathererState) -> Result<(), MetricsG } if let Ok(operations_metrics) = state.rollup_store.get_operations_count().await { - let (transactions, deposits, messages) = ( + let (transactions, privileged_transactions, messages) = ( operations_metrics[0], operations_metrics[1], operations_metrics[2], ); - METRICS.set_operation_by_type(MetricsOperationType::Deposits, deposits)?; + METRICS.set_operation_by_type( + MetricsOperationType::PrivilegedTransactions, + privileged_transactions, + )?; METRICS.set_operation_by_type(MetricsOperationType::L1Messages, messages)?; METRICS_TX.set_tx_count(transactions)?; } diff --git a/crates/l2/sequencer/mod.rs b/crates/l2/sequencer/mod.rs index 7b5ba6d496..ba4bf86824 100644 --- a/crates/l2/sequencer/mod.rs +++ b/crates/l2/sequencer/mod.rs @@ -22,7 +22,7 @@ pub mod block_producer; pub mod l1_committer; pub mod l1_proof_sender; pub mod l1_proof_verifier; -mod l1_watcher; +pub mod l1_watcher; #[cfg(feature = "metrics")] pub mod metrics; pub mod proof_coordinator; diff --git a/crates/l2/storage/src/api.rs b/crates/l2/storage/src/api.rs index e3e8e90b59..7a549858ac 100644 --- a/crates/l2/storage/src/api.rs +++ b/crates/l2/storage/src/api.rs @@ -53,13 +53,13 @@ pub trait StoreEngineRollup: Debug + Send + Sync { batch_number: u64, ) -> Result>, RollupStoreError>; - async fn store_deposit_logs_hash_by_batch_number( + async fn store_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, - deposit_logs_hash: H256, + privileged_transactions_hash: H256, ) -> Result<(), RollupStoreError>; - async fn get_deposit_logs_hash_by_batch_number( + async fn get_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, ) -> Result, RollupStoreError>; @@ -111,7 +111,7 @@ pub trait StoreEngineRollup: Debug + Send + Sync { async fn update_operations_count( &self, transaction_inc: u64, - deposits_inc: u64, + privileged_tx_inc: u64, messages_inc: u64, ) -> Result<(), RollupStoreError>; diff --git a/crates/l2/storage/src/store.rs b/crates/l2/storage/src/store.rs index 5ed86ffd6c..55ffd2d22b 100644 --- a/crates/l2/storage/src/store.rs +++ b/crates/l2/storage/src/store.rs @@ -72,7 +72,7 @@ impl Store { first_block: 0, last_block: 0, state_root: H256::zero(), - deposit_logs_hash: H256::zero(), + privileged_transactions_hash: H256::zero(), message_hashes: Vec::new(), blobs_bundle: BlobsBundle::empty(), commit_tx: None, @@ -135,22 +135,25 @@ impl Store { .await } - pub async fn get_deposit_logs_hash_by_batch( + pub async fn get_privileged_transactions_hash_by_batch( &self, batch_number: u64, ) -> Result, RollupStoreError> { self.engine - .get_deposit_logs_hash_by_batch_number(batch_number) + .get_privileged_transactions_hash_by_batch_number(batch_number) .await } - pub async fn store_deposit_logs_hash_by_batch( + pub async fn store_privileged_transactions_hash_by_batch( &self, batch_number: u64, - deposit_logs_hash: H256, + privileged_transactions_hash: H256, ) -> Result<(), RollupStoreError> { self.engine - .store_deposit_logs_hash_by_batch_number(batch_number, deposit_logs_hash) + .store_privileged_transactions_hash_by_batch_number( + batch_number, + privileged_transactions_hash, + ) .await } @@ -262,8 +265,8 @@ impl Store { .get_message_hashes_by_batch(batch_number) .await? .unwrap_or_default(); - let deposit_logs_hash = self - .get_deposit_logs_hash_by_batch(batch_number) + let privileged_transactions_hash = self + .get_privileged_transactions_hash_by_batch(batch_number) .await?.ok_or(RollupStoreError::Custom( "Failed while trying to retrieve the deposit logs hash of a known batch. This is a bug." .to_owned(), @@ -280,7 +283,7 @@ impl Store { state_root, blobs_bundle, message_hashes, - deposit_logs_hash, + privileged_transactions_hash, commit_tx, verify_tx, })) @@ -297,8 +300,11 @@ impl Store { .await?; self.store_message_hashes_by_batch(batch.number, batch.message_hashes) .await?; - self.store_deposit_logs_hash_by_batch(batch.number, batch.deposit_logs_hash) - .await?; + self.store_privileged_transactions_hash_by_batch( + batch.number, + batch.privileged_transactions_hash, + ) + .await?; self.store_blobs_by_batch(batch.number, batch.blobs_bundle.blobs) .await?; self.store_state_root_by_batch(batch.number, batch.state_root) @@ -317,11 +323,11 @@ impl Store { pub async fn update_operations_count( &self, transaction_inc: u64, - deposits_inc: u64, + privileged_tx_inc: u64, messages_inc: u64, ) -> Result<(), RollupStoreError> { self.engine - .update_operations_count(transaction_inc, deposits_inc, messages_inc) + .update_operations_count(transaction_inc, privileged_tx_inc, messages_inc) .await } diff --git a/crates/l2/storage/src/store_db/in_memory.rs b/crates/l2/storage/src/store_db/in_memory.rs index 4c52469853..fc075d6769 100644 --- a/crates/l2/storage/src/store_db/in_memory.rs +++ b/crates/l2/storage/src/store_db/in_memory.rs @@ -25,7 +25,7 @@ struct StoreInner { /// Map of batch number to block numbers block_numbers_by_batch: HashMap>, /// Map of batch number to deposit logs hash - deposit_logs_hashes: HashMap, + privileged_transactions_hashes: HashMap, /// Map of batch number to state root state_roots: HashMap, /// Map of batch number to blob @@ -122,24 +122,24 @@ impl StoreEngineRollup for Store { Ok(block_numbers) } - async fn store_deposit_logs_hash_by_batch_number( + async fn store_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, - deposit_logs_hash: H256, + privileged_transactions_hash: H256, ) -> Result<(), RollupStoreError> { self.inner()? - .deposit_logs_hashes - .insert(batch_number, deposit_logs_hash); + .privileged_transactions_hashes + .insert(batch_number, privileged_transactions_hash); Ok(()) } - async fn get_deposit_logs_hash_by_batch_number( + async fn get_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, ) -> Result, RollupStoreError> { Ok(self .inner()? - .deposit_logs_hashes + .privileged_transactions_hashes .get(&batch_number) .cloned()) } @@ -218,12 +218,12 @@ impl StoreEngineRollup for Store { async fn update_operations_count( &self, transaction_inc: u64, - deposits_inc: u64, + privileged_tx_inc: u64, messages_inc: u64, ) -> Result<(), RollupStoreError> { let mut values = self.inner()?.operations_counts; values[0] += transaction_inc; - values[1] += deposits_inc; + values[1] += privileged_tx_inc; values[2] += messages_inc; Ok(()) } @@ -302,7 +302,7 @@ impl StoreEngineRollup for Store { .block_numbers_by_batch .retain(|batch, _| *batch <= batch_number); store - .deposit_logs_hashes + .privileged_transactions_hashes .retain(|batch, _| *batch <= batch_number); store.state_roots.retain(|batch, _| *batch <= batch_number); store.blobs.retain(|batch, _| *batch <= batch_number); diff --git a/crates/l2/storage/src/store_db/libmdbx.rs b/crates/l2/storage/src/store_db/libmdbx.rs index 1a6d52730b..d05927e9e1 100644 --- a/crates/l2/storage/src/store_db/libmdbx.rs +++ b/crates/l2/storage/src/store_db/libmdbx.rs @@ -75,7 +75,7 @@ pub fn init_db(path: Option>) -> Result Result<(), RollupStoreError> { - self.write::( + self.write::( batch_number, - Rlp::from_bytes(deposit_logs_hash.encode_to_vec()), + Rlp::from_bytes(privileged_transactions_hash.encode_to_vec()), ) .await } - async fn get_deposit_logs_hash_by_batch_number( + async fn get_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, ) -> Result, RollupStoreError> { Ok(self - .read::(batch_number) + .read::(batch_number) .await? .map(|hash| hash.to())) } @@ -271,14 +271,14 @@ impl StoreEngineRollup for Store { async fn update_operations_count( &self, transaction_inc: u64, - deposits_inc: u64, + privileged_tx_inc: u64, messages_inc: u64, ) -> Result<(), RollupStoreError> { - let (transaction_count, messages_count, deposits_count) = { + let (transaction_count, messages_count, privileged_tx_count) = { let current_operations = self.get_operations_count().await?; ( current_operations[0] + transaction_inc, - current_operations[1] + deposits_inc, + current_operations[1] + privileged_tx_inc, current_operations[2] + messages_inc, ) }; @@ -286,7 +286,7 @@ impl StoreEngineRollup for Store { self.write::( 0, OperationsCountRLP::from_bytes( - vec![transaction_count, messages_count, deposits_count].encode_to_vec(), + vec![transaction_count, messages_count, privileged_tx_count].encode_to_vec(), ), ) .await @@ -375,7 +375,7 @@ impl StoreEngineRollup for Store { delete_starting_at::(&txn, last_kept_block + 1)?; delete_starting_at::(&txn, batch_number + 1)?; delete_starting_at::(&txn, batch_number + 1)?; - delete_starting_at::(&txn, batch_number + 1)?; + delete_starting_at::(&txn, batch_number + 1)?; delete_starting_at::(&txn, batch_number + 1)?; delete_starting_at::(&txn, batch_number + 1)?; txn.commit().map_err(RollupStoreError::LibmdbxError)?; @@ -412,7 +412,7 @@ table!( ); table!( - /// Transaction, deposits, messages count + /// Transaction, privileged transaction, messages count ( OperationsCount ) u64 => OperationsCountRLP ); @@ -427,8 +427,8 @@ table!( ); table!( - /// Deposit logs hash by batch number - ( DepositLogsHash ) u64 => Rlp + /// Privileged transactions hash by batch number + ( PrivilegedTransactionsHash ) u64 => Rlp ); table!( diff --git a/crates/l2/storage/src/store_db/redb.rs b/crates/l2/storage/src/store_db/redb.rs index b08bbe945d..d2ae9ac275 100644 --- a/crates/l2/storage/src/store_db/redb.rs +++ b/crates/l2/storage/src/store_db/redb.rs @@ -30,8 +30,8 @@ const BLOB_BUNDLES: TableDefinition>> = TableDefinition::new( const STATE_ROOTS: TableDefinition> = TableDefinition::new("StateRoots"); -const DEPOSIT_LOGS_HASHES: TableDefinition> = - TableDefinition::new("DepositLogsHashes"); +const PRIVILEGED_TRANSACTIONS_HASHES: TableDefinition> = + TableDefinition::new("PrivilegedTransactionHashes"); const LAST_SENT_BATCH_PROOF: TableDefinition = TableDefinition::new("LastSentBatchProof"); @@ -120,7 +120,7 @@ pub fn init_db() -> Result { table_creation_txn.open_table(OPERATIONS_COUNTS)?; table_creation_txn.open_table(BLOB_BUNDLES)?; table_creation_txn.open_table(STATE_ROOTS)?; - table_creation_txn.open_table(DEPOSIT_LOGS_HASHES)?; + table_creation_txn.open_table(PRIVILEGED_TRANSACTIONS_HASHES)?; table_creation_txn.open_table(BLOCK_NUMBERS_BY_BATCH)?; table_creation_txn.open_table(LAST_SENT_BATCH_PROOF)?; table_creation_txn.open_table(ACCOUNT_UPDATES_BY_BLOCK_NUMBER)?; @@ -207,21 +207,25 @@ impl StoreEngineRollup for RedBStoreRollup { Ok(exists) } - async fn store_deposit_logs_hash_by_batch_number( + async fn store_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, - deposit_logs_hash: H256, + privileged_transactions_hash: H256, ) -> Result<(), RollupStoreError> { - self.write(DEPOSIT_LOGS_HASHES, batch_number, deposit_logs_hash.into()) - .await + self.write( + PRIVILEGED_TRANSACTIONS_HASHES, + batch_number, + privileged_transactions_hash.into(), + ) + .await } - async fn get_deposit_logs_hash_by_batch_number( + async fn get_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, ) -> Result, RollupStoreError> { Ok(self - .read(DEPOSIT_LOGS_HASHES, batch_number) + .read(PRIVILEGED_TRANSACTIONS_HASHES, batch_number) .await? .map(|rlp| rlp.value().to())) } @@ -305,15 +309,15 @@ impl StoreEngineRollup for RedBStoreRollup { async fn update_operations_count( &self, transaction_inc: u64, - deposits_inc: u64, + privileged_tx_inc: u64, messages_inc: u64, ) -> Result<(), RollupStoreError> { - let (transaction_count, messages_count, deposits_count) = { + let (transaction_count, messages_count, privileged_tx_count) = { let current_operations = self.get_operations_count().await?; ( current_operations[0] + transaction_inc, current_operations[1] + messages_inc, - current_operations[2] + deposits_inc, + current_operations[2] + privileged_tx_inc, ) }; @@ -321,7 +325,7 @@ impl StoreEngineRollup for RedBStoreRollup { OPERATIONS_COUNTS, 0, OperationsCountRLP::from_bytes( - vec![transaction_count, messages_count, deposits_count].encode_to_vec(), + vec![transaction_count, messages_count, privileged_tx_count].encode_to_vec(), ), ) .await @@ -416,7 +420,7 @@ impl StoreEngineRollup for RedBStoreRollup { delete_starting_at(&txn, BATCHES_BY_BLOCK_NUMBER_TABLE, last_kept_block + 1)?; delete_starting_at(&txn, MESSAGES_BY_BATCH, batch_number + 1)?; delete_starting_at(&txn, BLOCK_NUMBERS_BY_BATCH, batch_number + 1)?; - delete_starting_at(&txn, DEPOSIT_LOGS_HASHES, batch_number + 1)?; + delete_starting_at(&txn, PRIVILEGED_TRANSACTIONS_HASHES, batch_number + 1)?; delete_starting_at(&txn, STATE_ROOTS, batch_number + 1)?; delete_starting_at(&txn, BLOB_BUNDLES, batch_number + 1)?; txn.commit()?; diff --git a/crates/l2/storage/src/store_db/sql.rs b/crates/l2/storage/src/store_db/sql.rs index a7a4d965b2..54cd65bc27 100644 --- a/crates/l2/storage/src/store_db/sql.rs +++ b/crates/l2/storage/src/store_db/sql.rs @@ -25,13 +25,13 @@ impl Debug for SQLStore { const DB_SCHEMA: [&str; 13] = [ "CREATE TABLE blocks (block_number INT PRIMARY KEY, batch INT)", "CREATE TABLE messages (batch INT, idx INT, message_hash BLOB, PRIMARY KEY (batch, idx))", - "CREATE TABLE deposits (batch INT PRIMARY KEY, deposit_hash BLOB)", + "CREATE TABLE privileged_transactions (batch INT PRIMARY KEY, transactions_hash BLOB)", "CREATE TABLE state_roots (batch INT PRIMARY KEY, state_root BLOB)", "CREATE TABLE blob_bundles (batch INT, idx INT, blob_bundle BLOB, PRIMARY KEY (batch, idx))", "CREATE TABLE account_updates (block_number INT PRIMARY KEY, updates BLOB)", "CREATE TABLE commit_txs (batch INT PRIMARY KEY, commit_tx BLOB)", "CREATE TABLE verify_txs (batch INT PRIMARY KEY, verify_tx BLOB)", - "CREATE TABLE operation_count (_id INT PRIMARY KEY, transactions INT, deposits INT, messages INT)", + "CREATE TABLE operation_count (_id INT PRIMARY KEY, transactions INT, privileged_transactions INT, messages INT)", "INSERT INTO operation_count VALUES (0, 0, 0, 0)", "CREATE TABLE latest_sent (_id INT PRIMARY KEY, batch INT)", "INSERT INTO latest_sent VALUES (0, 0)", @@ -216,31 +216,35 @@ impl StoreEngineRollup for SQLStore { } } - async fn store_deposit_logs_hash_by_batch_number( + async fn store_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, - deposit_logs_hash: H256, + privileged_transactions_hash: H256, ) -> Result<(), RollupStoreError> { self.execute_in_tx(vec![ ( - "DELETE FROM deposits WHERE batch = ?1", + "DELETE FROM privileged_transactions WHERE batch = ?1", vec![batch_number].into_params()?, ), ( - "INSERT INTO deposits VALUES (?1, ?2)", - (batch_number, Vec::from(deposit_logs_hash.to_fixed_bytes())).into_params()?, + "INSERT INTO privileged_transactions VALUES (?1, ?2)", + ( + batch_number, + Vec::from(privileged_transactions_hash.to_fixed_bytes()), + ) + .into_params()?, ), ]) .await } - async fn get_deposit_logs_hash_by_batch_number( + async fn get_privileged_transactions_hash_by_batch_number( &self, batch_number: u64, ) -> Result, RollupStoreError> { let mut rows = self .query( - "SELECT * from deposits WHERE batch = ?1", + "SELECT * from privileged_transactions WHERE batch = ?1", vec![batch_number], ) .await?; @@ -394,12 +398,12 @@ impl StoreEngineRollup for SQLStore { async fn update_operations_count( &self, transaction_inc: u64, - deposits_inc: u64, + privileged_transactions_inc: u64, messages_inc: u64, ) -> Result<(), RollupStoreError> { self.execute( - "UPDATE operation_count SET transactions = transactions + ?1, deposits = deposits + ?2, messages = messages + ?3", - (transaction_inc, deposits_inc, messages_inc)).await?; + "UPDATE operation_count SET transactions = transactions + ?1, privileged_transactions = privileged_transactions + ?2, messages = messages + ?3", + (transaction_inc, privileged_transactions_inc, messages_inc)).await?; Ok(()) } @@ -491,7 +495,7 @@ impl StoreEngineRollup for SQLStore { [batch_number].into_params()?, ), ( - "DELETE FROM deposits WHERE batch > ?1", + "DELETE FROM privileged_transactions WHERE batch > ?1", [batch_number].into_params()?, ), ( @@ -564,7 +568,7 @@ mod tests { let tables = [ "blocks", "messages", - "deposits", + "privileged_transactions", "state_roots", "blob_bundles", "account_updates", @@ -593,8 +597,8 @@ mod tests { ("messages", "batch") => "INT", ("messages", "idx") => "INT", ("messages", "message_hash") => "BLOB", - ("deposits", "batch") => "INT", - ("deposits", "deposit_hash") => "BLOB", + ("privileged_transactions", "batch") => "INT", + ("privileged_transactions", "transactions_hash") => "BLOB", ("state_roots", "batch") => "INT", ("state_roots", "state_root") => "BLOB", ("blob_bundles", "batch") => "INT", @@ -604,7 +608,7 @@ mod tests { ("account_updates", "updates") => "BLOB", ("operation_count", "_id") => "INT", ("operation_count", "transactions") => "INT", - ("operation_count", "deposits") => "INT", + ("operation_count", "privileged_transactions") => "INT", ("operation_count", "messages") => "INT", ("latest_sent", "_id") => "INT", ("latest_sent", "batch") => "INT", diff --git a/crates/l2/tee/quote-gen/src/main.rs b/crates/l2/tee/quote-gen/src/main.rs index 6b967796b5..5d18290004 100644 --- a/crates/l2/tee/quote-gen/src/main.rs +++ b/crates/l2/tee/quote-gen/src/main.rs @@ -47,7 +47,7 @@ fn calculate_transition(input: ProgramInput) -> Result, String> { #[cfg(feature = "l2")] let l1messages_merkle_root_bytes = output.l1messages_merkle_root.0.to_vec(); #[cfg(feature = "l2")] - let deposit_logs_hash_bytes = output.deposit_logs_hash.0.to_vec(); + let privileged_transactions_hash_bytes = output.privileged_transactions_hash.0.to_vec(); #[cfg(feature = "l2")] let blob_versioned_hash_bytes = output.blob_versioned_hash.0.to_vec(); @@ -57,7 +57,7 @@ fn calculate_transition(input: ProgramInput) -> Result, String> { #[cfg(feature = "l2")] Value::FixedBytes(l1messages_merkle_root_bytes.into()), #[cfg(feature = "l2")] - Value::FixedBytes(deposit_logs_hash_bytes.into()), + Value::FixedBytes(privileged_transactions_hash_bytes.into()), #[cfg(feature = "l2")] Value::FixedBytes(blob_versioned_hash_bytes.into()), Value::FixedBytes(last_block_hash_bytes.into()), diff --git a/crates/l2/tests/tests.rs b/crates/l2/tests/tests.rs index cd123ff3a9..e788af1a3d 100644 --- a/crates/l2/tests/tests.rs +++ b/crates/l2/tests/tests.rs @@ -3,6 +3,7 @@ use bytes::Bytes; use ethereum_types::{Address, U256}; use ethrex_common::{H160, types::BlockNumber}; +use ethrex_l2::sequencer::l1_watcher::PrivilegedTransactionData; use ethrex_l2_common::calldata::Value; use ethrex_l2_sdk::calldata::{self}; use ethrex_l2_sdk::l1_to_l2_tx_data::L1ToL2TransactionData; @@ -100,7 +101,7 @@ async fn l2_integration_test() -> Result<(), Box> { ) .await?; - test_transfer_with_deposit( + test_transfer_with_privileged_tx( &rich_wallet_private_key, &transfer_return_private_key, ð_client, @@ -110,12 +111,16 @@ async fn l2_integration_test() -> Result<(), Box> { test_gas_burning(ð_client).await?; - test_deposit_with_contract_call(&proposer_client, ð_client).await?; + test_privileged_tx_with_contract_call(&proposer_client, ð_client).await?; - test_deposit_with_contract_call_revert(&proposer_client, ð_client).await?; + test_privileged_tx_with_contract_call_revert(&proposer_client, ð_client).await?; - test_deposit_not_enough_balance(&transfer_return_private_key, ð_client, &proposer_client) - .await?; + test_privileged_tx_not_enough_balance( + &transfer_return_private_key, + ð_client, + &proposer_client, + ) + .await?; test_erc20_roundtrip(bridge_address, &proposer_client, ð_client).await?; @@ -142,7 +147,7 @@ async fn l2_integration_test() -> Result<(), Box> { /// In this test we deploy a contract on L2 and call it from L1 using the CommonBridge contract. /// We call the contract by making a deposit from L1 to L2 with the recipient being the rich account. /// The deposit will trigger the call to the contract. -async fn test_deposit_with_contract_call( +async fn test_privileged_tx_with_contract_call( proposer_client: &EthClient, eth_client: &EthClient, ) -> Result<(), Box> { @@ -219,7 +224,7 @@ async fn test_deposit_with_contract_call( /// Test the deployment of a contract on L2 and call it from L1 using the CommonBridge contract. /// The call to the contract should revert but the deposit should be successful. -async fn test_deposit_with_contract_call_revert( +async fn test_privileged_tx_with_contract_call_revert( proposer_client: &EthClient, eth_client: &EthClient, ) -> Result<(), Box> { @@ -562,7 +567,7 @@ async fn test_transfer( Ok(()) } -async fn test_transfer_with_deposit( +async fn test_transfer_with_privileged_tx( transferer_private_key: &SecretKey, receiver_private_key: &SecretKey, eth_client: &EthClient, @@ -641,7 +646,7 @@ async fn test_gas_burning(eth_client: &EthClient) -> Result<(), Box Result> { - let topic = keccak(b"L1ToL2Message(uint256,address,uint256,address,uint256,bytes,bytes32)"); + let topic = keccak(b"PrivilegedTxSent(address,address,uint256,uint256,uint256,bytes)"); let logs = eth_client .get_logs( U256::from(l1_receipt_block_number), @@ -1274,8 +1279,18 @@ async fn wait_for_l2_deposit_receipt( topic, ) .await?; + let data = PrivilegedTransactionData::from_log(logs.first().unwrap().log.clone())?; - let l2_deposit_tx_hash = H256::from_slice(logs.first().unwrap().log.data.get(96..128).unwrap()); + let l2_deposit_tx_hash = data + .into_tx( + eth_client, + proposer_client.get_chain_id().await?.try_into().unwrap(), + 0, + ) + .await + .unwrap() + .get_privileged_hash() + .unwrap(); println!("Waiting for deposit transaction receipt on L2"); diff --git a/crates/networking/rpc/clients/eth/mod.rs b/crates/networking/rpc/clients/eth/mod.rs index ea600637d8..2bbfa0ce3d 100644 --- a/crates/networking/rpc/clients/eth/mod.rs +++ b/crates/networking/rpc/clients/eth/mod.rs @@ -1071,12 +1071,12 @@ impl EthClient { .await } - pub async fn get_pending_deposit_logs( + pub async fn get_pending_privileged_transactions( &self, common_bridge_address: Address, ) -> Result, EthClientError> { let response = self - ._generic_call(b"getPendingDepositLogs()", common_bridge_address) + ._generic_call(b"getPendingTransactionHashes()", common_bridge_address) .await?; Self::from_hex_string_to_h256_array(&response) } diff --git a/docs/l2/state_diffs.md b/docs/l2/state_diffs.md index 8649ac6679..3866aceb62 100644 --- a/docs/l2/state_diffs.md +++ b/docs/l2/state_diffs.md @@ -40,7 +40,7 @@ The full state diff sent for each batch will then be a sequence of bytes encoded - Note that values `8` and `16` are mutually exclusive, and if `type` is greater or equal to `4`, then the address is a contract. Each address can only appear once in the list. - Next the `WithdrawalLogs` field: - First two bytes are the number of entries, then come the tuples `(to_u160, amount_u256, tx_hash_u256)`. -- Next the `DepositLogs` field: +- Next the `PrivilegedTransactionLogs` field: - First two bytes are the number of entries, then come the tuples `(to_u160, value_u256)`. - In case of the only changes on an account are produced by withdrawals, the `ModifiedAccounts` for that address field must be omitted. In this case, the state diff can be computed by incrementing the nonce in one unit and subtracting the amount from the balance. @@ -63,8 +63,8 @@ number_of_modified_accounts_u16 || // Withdraw Logs number_of_withdraw_logs_u16 || (to_u160 || amount_u256 || tx_hash_u256) ... -// Deposit Logs -number_of_deposit_logs_u16 || +// Privileged Transactions Logs +number_of_privileged_transaction_logs_u16 || (to_u160 || value_u256) ... ```