-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: modify_spec_id * wip: block and chain drivers * feature: block and chain drivers * chore: update ascii diagram * chore: update state diagram * fix: aliases
- Loading branch information
Showing
11 changed files
with
519 additions
and
163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use crate::{driver::RunTxResult, Block, BlockDriver, EvmNeedsTx, Shanghai}; | ||
use alloy_consensus::TxEnvelope; | ||
use alloy_primitives::U256; | ||
use revm::{ | ||
primitives::{BlobExcessGasAndPrice, BlockEnv, EVMError}, | ||
Database, DatabaseCommit, | ||
}; | ||
|
||
impl<'a> From<&'a alloy_rpc_types_eth::Block<TxEnvelope>> for Shanghai<'a> { | ||
fn from(block: &'a alloy_rpc_types_eth::Block<TxEnvelope>) -> Self { | ||
block.withdrawals.as_ref().map(|s| Shanghai::new(s)).unwrap_or_default() | ||
} | ||
} | ||
|
||
impl Block for alloy_rpc_types_eth::Header { | ||
fn fill_block_env(&self, block_env: &mut revm::primitives::BlockEnv) { | ||
let BlockEnv { | ||
number, | ||
coinbase, | ||
timestamp, | ||
gas_limit, | ||
basefee, | ||
difficulty, | ||
prevrandao, | ||
blob_excess_gas_and_price, | ||
} = block_env; | ||
*number = U256::from(self.number.unwrap_or_default()); | ||
*coinbase = self.miner; | ||
*timestamp = U256::from(self.timestamp); | ||
*gas_limit = U256::from(self.gas_limit); | ||
*basefee = U256::from(self.base_fee_per_gas.unwrap_or_default()); | ||
*difficulty = U256::from(self.difficulty); | ||
*prevrandao = self.mix_hash; | ||
*blob_excess_gas_and_price = | ||
self.blob_gas_used.map(|ebg| BlobExcessGasAndPrice::new(ebg as u64)); | ||
} | ||
} | ||
|
||
/// Error during Ethereum consensus checks. | ||
#[derive(thiserror::Error)] | ||
pub enum AlloyBlockError<Db: Database> { | ||
/// An error occurred in the EVM. | ||
#[error("EVM error")] | ||
EvmError(revm::primitives::EVMError<Db::Error>), | ||
|
||
/// Block contained only tx hashes, without transactions | ||
#[error("Block contained only tx hashes, without transactions")] | ||
MissingTransactions, | ||
} | ||
|
||
impl<Db: Database> std::fmt::Debug for AlloyBlockError<Db> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
match self { | ||
Self::EvmError(_) => f.debug_struct("EvmError").finish_non_exhaustive(), | ||
Self::MissingTransactions => f.write_str("MissingTransactions"), | ||
} | ||
} | ||
} | ||
|
||
impl<Db: Database> From<EVMError<Db::Error>> for AlloyBlockError<Db> { | ||
fn from(e: EVMError<Db::Error>) -> Self { | ||
Self::EvmError(e) | ||
} | ||
} | ||
|
||
impl<'b> BlockDriver<'b, Shanghai<'b>> for alloy_rpc_types_eth::Block<TxEnvelope> { | ||
type Block = alloy_rpc_types_eth::Header; | ||
|
||
// TODO: Implement this | ||
type Error<Db: Database> = AlloyBlockError<Db>; | ||
|
||
fn block(&self) -> &Self::Block { | ||
&self.header | ||
} | ||
|
||
fn context(&'b self) -> Shanghai<'b> { | ||
self.withdrawals.as_ref().map(|w| Shanghai::new(w.as_slice())).unwrap_or_default() | ||
} | ||
|
||
fn run_txns<'a, Ext, Db: Database + DatabaseCommit>( | ||
&self, | ||
mut trevm: EvmNeedsTx<'a, Ext, Db, Shanghai<'b>>, | ||
) -> RunTxResult<'a, 'b, Ext, Db, Shanghai<'b>, Self> { | ||
if !self.transactions.is_full() { | ||
return Err(trevm.errored(AlloyBlockError::MissingTransactions)); | ||
} | ||
|
||
for transaction in self.transactions.txns() { | ||
trevm = trevm.run_tx(transaction).map_err(|e| e.err_into())?.accept(); | ||
} | ||
Ok(trevm) | ||
} | ||
|
||
fn post_block_checks<Ext, Db: Database + DatabaseCommit>( | ||
&self, | ||
_trevm: &crate::EvmBlockComplete<'_, Ext, Db, Shanghai<'b>>, | ||
) -> Result<(), Self::Error<Db>> { | ||
// TODO | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
use crate::{Block, BlockContext, EvmBlockComplete, EvmBlockDriverErrored, EvmNeedsTx}; | ||
use revm::{primitives::EVMError, Database, DatabaseCommit}; | ||
|
||
/// The result of running transactions for a block driver. | ||
pub type RunTxResult<'a, 'b, Ext, Db, C, T> = | ||
Result<EvmNeedsTx<'a, Ext, Db, C>, EvmBlockDriverErrored<'a, 'b, Ext, Db, C, T>>; | ||
|
||
/// The result of driving a block to completion. | ||
pub type DriveBlockResult<'a, 'b, Ext, Db, C, T> = | ||
Result<EvmBlockComplete<'a, Ext, Db, C>, EvmBlockDriverErrored<'a, 'b, Ext, Db, C, T>>; | ||
|
||
/// Driver for a single trevm block. This trait allows a type to specify the | ||
/// entire lifecycle of a trevm block, from opening the block to driving the | ||
/// trevm to completion. | ||
pub trait BlockDriver<'b, C: BlockContext> | ||
where | ||
Self: 'b, | ||
{ | ||
/// The [`Block`] filler for this driver. | ||
type Block: Block; | ||
|
||
/// An error type for this driver. | ||
type Error<Db: Database>: std::error::Error | ||
+ From<EVMError<Db::Error>> | ||
+ From<<C as BlockContext>::Error<Db>>; | ||
|
||
/// Get a reference to the block filler for this driver. | ||
fn block(&self) -> &Self::Block; | ||
|
||
/// Get the context for this block. | ||
fn context(&'b self) -> C; | ||
|
||
/// Run the transactions for the block. | ||
fn run_txns<'a, Ext, Db: Database + DatabaseCommit>( | ||
&self, | ||
trevm: EvmNeedsTx<'a, Ext, Db, C>, | ||
) -> RunTxResult<'a, 'b, Ext, Db, C, Self>; | ||
|
||
/// Run post | ||
fn post_block_checks<Ext, Db: Database + DatabaseCommit>( | ||
&self, | ||
trevm: &EvmBlockComplete<'_, Ext, Db, C>, | ||
) -> Result<(), Self::Error<Db>>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use crate::{BlockContext, BlockDriver, EvmBlockComplete, EvmChainDriverErrored, EvmNeedsBlock}; | ||
use revm::{ | ||
primitives::{EVMError, SpecId}, | ||
Database, DatabaseCommit, | ||
}; | ||
|
||
/// The result of driving a chain to completion. | ||
pub type DriveChainResult<'a, 'b, Ext, Db, C, D> = | ||
Result<(Vec<C>, EvmNeedsBlock<'a, Ext, Db>), EvmChainDriverErrored<'a, 'b, Ext, Db, C, D>>; | ||
|
||
/// Driver for a chain of blocks. | ||
pub trait ChainDriver<'b, C: BlockContext> { | ||
/// The block driver for this chain. | ||
type BlockDriver: BlockDriver<'b, C>; | ||
|
||
/// An error type for this driver. | ||
type Error<Db: Database>: std::error::Error | ||
+ From<EVMError<Db::Error>> | ||
+ From<<C as BlockContext>::Error<Db>> | ||
+ From<<Self::BlockDriver as BlockDriver<'b, C>>::Error<Db>>; | ||
|
||
/// Get the spec id for a block. | ||
fn spec_id_for(&self, block: &<Self::BlockDriver as BlockDriver<'b, C>>::Block) -> SpecId; | ||
|
||
/// Get the blocks in this chain. The blocks should be in order, and this | ||
/// function MUST NOT return an empty slice. | ||
fn blocks(&self) -> &[Self::BlockDriver]; | ||
|
||
/// Checks that run between blocks, e.g. 1559 base fee calculation, | ||
/// or parent-child relationships. | ||
/// | ||
/// The `idx` parameter is the index of the block in the chain. | ||
fn check_interblock<Ext, Db: Database + DatabaseCommit>( | ||
&self, | ||
trevm: &EvmBlockComplete<'_, Ext, Db, C>, | ||
idx: usize, | ||
) -> Result<(), Self::Error<Db>>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
mod alloy; | ||
pub use alloy::AlloyBlockError; | ||
|
||
mod block; | ||
pub use block::{BlockDriver, DriveBlockResult, RunTxResult}; | ||
|
||
mod chain; | ||
pub use chain::{ChainDriver, DriveChainResult}; |
Oops, something went wrong.