|
| 1 | +use crate::{driver::RunTxResult, Block, BlockDriver, EvmNeedsTx, Shanghai}; |
| 2 | +use alloy_consensus::TxEnvelope; |
| 3 | +use alloy_primitives::U256; |
| 4 | +use revm::{ |
| 5 | + primitives::{BlobExcessGasAndPrice, BlockEnv, EVMError}, |
| 6 | + Database, DatabaseCommit, |
| 7 | +}; |
| 8 | + |
| 9 | +impl<'a> From<&'a alloy_rpc_types_eth::Block<TxEnvelope>> for Shanghai<'a> { |
| 10 | + fn from(block: &'a alloy_rpc_types_eth::Block<TxEnvelope>) -> Self { |
| 11 | + block.withdrawals.as_ref().map(|s| Shanghai::new(s)).unwrap_or_default() |
| 12 | + } |
| 13 | +} |
| 14 | + |
| 15 | +impl Block for alloy_rpc_types_eth::Header { |
| 16 | + fn fill_block_env(&self, block_env: &mut revm::primitives::BlockEnv) { |
| 17 | + let BlockEnv { |
| 18 | + number, |
| 19 | + coinbase, |
| 20 | + timestamp, |
| 21 | + gas_limit, |
| 22 | + basefee, |
| 23 | + difficulty, |
| 24 | + prevrandao, |
| 25 | + blob_excess_gas_and_price, |
| 26 | + } = block_env; |
| 27 | + *number = U256::from(self.number.unwrap_or_default()); |
| 28 | + *coinbase = self.miner; |
| 29 | + *timestamp = U256::from(self.timestamp); |
| 30 | + *gas_limit = U256::from(self.gas_limit); |
| 31 | + *basefee = U256::from(self.base_fee_per_gas.unwrap_or_default()); |
| 32 | + *difficulty = U256::from(self.difficulty); |
| 33 | + *prevrandao = self.mix_hash; |
| 34 | + *blob_excess_gas_and_price = |
| 35 | + self.blob_gas_used.map(|ebg| BlobExcessGasAndPrice::new(ebg as u64)); |
| 36 | + } |
| 37 | +} |
| 38 | + |
| 39 | +/// Error during Ethereum consensus checks. |
| 40 | +#[derive(thiserror::Error)] |
| 41 | +pub enum AlloyBlockError<Db: Database> { |
| 42 | + /// An error occurred in the EVM. |
| 43 | + #[error("EVM error")] |
| 44 | + EvmError(revm::primitives::EVMError<Db::Error>), |
| 45 | + |
| 46 | + /// Block contained only tx hashes, without transactions |
| 47 | + #[error("Block contained only tx hashes, without transactions")] |
| 48 | + MissingTransactions, |
| 49 | +} |
| 50 | + |
| 51 | +impl<Db: Database> std::fmt::Debug for AlloyBlockError<Db> { |
| 52 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 53 | + match self { |
| 54 | + Self::EvmError(_) => f.debug_struct("EvmError").finish_non_exhaustive(), |
| 55 | + Self::MissingTransactions => f.write_str("MissingTransactions"), |
| 56 | + } |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +impl<Db: Database> From<EVMError<Db::Error>> for AlloyBlockError<Db> { |
| 61 | + fn from(e: EVMError<Db::Error>) -> Self { |
| 62 | + Self::EvmError(e) |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +impl<'b> BlockDriver<'b, Shanghai<'b>> for alloy_rpc_types_eth::Block<TxEnvelope> { |
| 67 | + type Block = alloy_rpc_types_eth::Header; |
| 68 | + |
| 69 | + // TODO: Implement this |
| 70 | + type Error<Db: Database> = AlloyBlockError<Db>; |
| 71 | + |
| 72 | + fn block(&self) -> &Self::Block { |
| 73 | + &self.header |
| 74 | + } |
| 75 | + |
| 76 | + fn context(&'b self) -> Shanghai<'b> { |
| 77 | + self.withdrawals.as_ref().map(|w| Shanghai::new(w.as_slice())).unwrap_or_default() |
| 78 | + } |
| 79 | + |
| 80 | + fn run_txns<'a, Ext, Db: Database + DatabaseCommit>( |
| 81 | + &self, |
| 82 | + mut trevm: EvmNeedsTx<'a, Ext, Db, Shanghai<'b>>, |
| 83 | + ) -> RunTxResult<'a, 'b, Ext, Db, Shanghai<'b>, Self> { |
| 84 | + if !self.transactions.is_full() { |
| 85 | + return Err(trevm.errored(AlloyBlockError::MissingTransactions)); |
| 86 | + } |
| 87 | + |
| 88 | + for transaction in self.transactions.txns() { |
| 89 | + trevm = trevm.run_tx(transaction).map_err(|e| e.err_into())?.accept(); |
| 90 | + } |
| 91 | + Ok(trevm) |
| 92 | + } |
| 93 | + |
| 94 | + fn post_block_checks<Ext, Db: Database + DatabaseCommit>( |
| 95 | + &self, |
| 96 | + _trevm: &crate::EvmBlockComplete<'_, Ext, Db, Shanghai<'b>>, |
| 97 | + ) -> Result<(), Self::Error<Db>> { |
| 98 | + // TODO |
| 99 | + Ok(()) |
| 100 | + } |
| 101 | +} |
0 commit comments