From 31dc6c0b40e73d2fd6d50aa502549ea4f2251d80 Mon Sep 17 00:00:00 2001 From: Maximo Palopoli <96491141+maximopalopoli@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:49:24 -0300 Subject: [PATCH] feat(levm): implement blobhash logic (#940) **Motivation** The motivation is to implement the blobhash opcode, since was not implemented yet. **Description** Main changes: - Adds an atribute to store the blob hashes in Environment type - implements blobhash logic, basicly taking an element of the vec of blob hashes and pushing it to the stack - To do that, add some posible errors to VMError enum Closes #933 --- crates/vm/levm/src/errors.rs | 2 ++ crates/vm/levm/src/opcode_handlers/block.rs | 24 ++++++++++++++++++--- crates/vm/levm/src/utils.rs | 1 + crates/vm/levm/src/vm.rs | 3 +++ crates/vm/levm/tests/tests.rs | 8 +++++++ 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/crates/vm/levm/src/errors.rs b/crates/vm/levm/src/errors.rs index d1f8a59da..12c107da1 100644 --- a/crates/vm/levm/src/errors.rs +++ b/crates/vm/levm/src/errors.rs @@ -19,6 +19,8 @@ pub enum VMError { OverflowInArithmeticOp, FatalError, InvalidTransaction, + MissingBlobHashes, + BlobHashIndexOutOfBounds, RevertOpcode, SenderAccountDoesNotExist, SenderAccountShouldNotHaveBytecode, diff --git a/crates/vm/levm/src/opcode_handlers/block.rs b/crates/vm/levm/src/opcode_handlers/block.rs index 5698087ee..739769108 100644 --- a/crates/vm/levm/src/opcode_handlers/block.rs +++ b/crates/vm/levm/src/opcode_handlers/block.rs @@ -2,6 +2,7 @@ use crate::{ block::LAST_AVAILABLE_BLOCK_LIMIT, constants::{BLOB_BASE_FEE_UPDATE_FRACTION, MIN_BASE_FEE_PER_BLOB_GAS}, }; +use keccak_hash::H256; // Block Information (11) // Opcodes: BLOCKHASH, COINBASE, TIMESTAMP, NUMBER, PREVRANDAO, GASLIMIT, CHAINID, SELFBALANCE, BASEFEE, BLOBHASH, BLOBBASEFEE @@ -143,16 +144,33 @@ impl VM { } // BLOBHASH operation + /// Currently not tested pub fn op_blobhash( &mut self, current_call_frame: &mut CallFrame, ) -> Result { self.increase_consumed_gas(current_call_frame, gas_cost::BLOBHASH)?; - // Should push in stack the blob hash - unimplemented!("when we have tx implemented"); + let index = current_call_frame.stack.pop()?.as_usize(); - // Ok(OpcodeSuccess::Continue) + let blob_hash: H256 = match &self.env.tx_blob_hashes { + Some(vec) => match vec.get(index) { + Some(el) => *el, + None => { + return Err(VMError::BlobHashIndexOutOfBounds); + } + }, + None => { + return Err(VMError::MissingBlobHashes); + } + }; + + // Could not find a better way to translate from H256 to U256 + let u256_blob = U256::from(blob_hash.as_bytes()); + + current_call_frame.stack.push(u256_blob)?; + + Ok(OpcodeSuccess::Continue) } fn get_blob_gasprice(&mut self) -> U256 { diff --git a/crates/vm/levm/src/utils.rs b/crates/vm/levm/src/utils.rs index 34d915abc..599b3efea 100644 --- a/crates/vm/levm/src/utils.rs +++ b/crates/vm/levm/src/utils.rs @@ -71,5 +71,6 @@ pub fn new_vm_with_ops_addr_bal(bytecode: Bytes, address: Address, balance: U256 state, Default::default(), Default::default(), + Default::default(), ) } diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index bbca1e0dc..ae305f6d9 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -174,6 +174,7 @@ pub struct Environment { pub gas_price: U256, pub block_excess_blob_gas: Option, pub block_blob_gas_used: Option, + pub tx_blob_hashes: Option>, } #[derive(Debug, Clone, Default)] @@ -218,6 +219,7 @@ impl VM { db: Db, block_blob_gas_used: Option, block_excess_blob_gas: Option, + tx_blob_hashes: Option>, ) -> Self { // TODO: This handles only CALL transactions. let bytecode = db.get_account_bytecode(&to); @@ -259,6 +261,7 @@ impl VM { gas_price, block_blob_gas_used, block_excess_blob_gas, + tx_blob_hashes, }; Self { diff --git a/crates/vm/levm/tests/tests.rs b/crates/vm/levm/tests/tests.rs index e90307734..4ddd2e8ee 100644 --- a/crates/vm/levm/tests/tests.rs +++ b/crates/vm/levm/tests/tests.rs @@ -3860,6 +3860,7 @@ fn caller_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap(); @@ -3901,6 +3902,7 @@ fn origin_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap(); @@ -3968,6 +3970,7 @@ fn address_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap(); @@ -4011,6 +4014,7 @@ fn selfbalance_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap(); @@ -4050,6 +4054,7 @@ fn callvalue_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap(); @@ -4088,6 +4093,7 @@ fn codesize_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap(); @@ -4128,6 +4134,7 @@ fn gasprice_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap(); @@ -4185,6 +4192,7 @@ fn codecopy_op() { db, Default::default(), Default::default(), + Default::default(), ); let mut current_call_frame = vm.call_frames.pop().unwrap();