use crate::{
db::{StateAcc, TryStateAcc},
driver::DriveBlockResult,
helpers::Ctx,
Block, BlockDriver, ChainDriver, DriveChainResult, EvmErrored, EvmNeedsBlock, EvmNeedsTx,
};
use revm::{
context::ContextTr,
database::{states::bundle_state::BundleRetention, BundleState},
Database, DatabaseCommit, Inspector,
};
impl<Db, Insp> EvmNeedsBlock<Db, Insp>
where
Db: Database,
Insp: Inspector<Ctx<Db>>,
{
pub fn drive_block<D>(self, driver: &mut D) -> DriveBlockResult<D, Db, Insp>
where
D: BlockDriver<Db, Insp>,
Db: DatabaseCommit,
{
let trevm = self.fill_block(driver.block());
let trevm = driver.run_txns(trevm)?;
let trevm = trevm.close_block();
match driver.post_block(&trevm) {
Ok(_) => Ok(trevm),
Err(e) => Err(trevm.errored(e)),
}
}
pub fn drive_chain<D>(self, driver: &mut D) -> DriveChainResult<D, Db, Insp>
where
D: ChainDriver<Db, Insp>,
Db: DatabaseCommit,
{
let block_count = driver.blocks().len();
let mut trevm = self
.drive_block(&mut driver.blocks()[0])
.map_err(EvmErrored::err_into::<<D as ChainDriver<Db, Insp>>::Error>)?;
if let Err(e) = driver.interblock(&trevm, 0) {
return Err(trevm.errored(e));
}
for i in 1..block_count {
trevm = {
let trevm = trevm
.drive_block(&mut driver.blocks()[i])
.map_err(EvmErrored::err_into::<<D as ChainDriver<Db, Insp>>::Error>)?;
if let Err(e) = driver.interblock(&trevm, i) {
return Err(trevm.errored(e));
}
trevm
};
}
Ok(trevm)
}
pub fn fill_block<B: Block>(mut self, filler: &B) -> EvmNeedsTx<Db, Insp> {
filler.fill_block(self.inner_mut_unchecked());
unsafe { core::mem::transmute(self) }
}
}
impl<Db, Insp> EvmNeedsBlock<Db, Insp>
where
Db: Database + StateAcc,
Insp: Inspector<Ctx<Db>>,
{
pub fn finish(self) -> BundleState {
let Self { inner: mut evm, .. } = self;
evm.db_mut().merge_transitions(BundleRetention::Reverts);
let bundle = evm.db_mut().take_bundle();
bundle
}
}
impl<Db, Insp> EvmNeedsBlock<Db, Insp>
where
Db: Database + TryStateAcc,
Insp: Inspector<Ctx<Db>>,
{
pub fn try_finish(
mut self,
) -> Result<BundleState, EvmErrored<Db, Insp, <Db as TryStateAcc>::Error>> {
let db = self.inner.db_mut();
trevm_try!(db.try_merge_transitions(BundleRetention::Reverts), self);
let bundle = trevm_try!(db.try_take_bundle(), self);
Ok(bundle)
}
}