arbiter_core/
coprocessor.rs

1//! The [`Coprocessor`] is used to process calls and can access read-only from
2//! the [`Environment`]'s database while staying up to date with the
3//! latest state of the [`Environment`]'s database.
4
5use std::convert::Infallible;
6
7use revm_primitives::{EVMError, ResultAndState};
8
9use super::*;
10use crate::environment::Environment;
11
12/// A [`Coprocessor`] is used to process calls and can access read-only from the
13/// [`Environment`]'s database. This can eventually be used for things like
14/// parallelized compute for agents that are not currently sending transactions
15/// that need to be processed by the [`Environment`], but are instead using the
16/// current state to make decisions.
17pub struct Coprocessor<'a> {
18    evm: Evm<'a, (), ArbiterDB>,
19}
20
21impl<'a> Coprocessor<'a> {
22    /// Create a new `Coprocessor` with the given `Environment`.
23    pub fn new(environment: &Environment) -> Self {
24        let db = environment.db.clone();
25        let evm = Evm::builder().with_db(db).build();
26        Self { evm }
27    }
28
29    // TODO: Should probably take in a TxEnv or something.
30    /// Used as an entrypoint to process a call with the `Coprocessor`.
31    pub fn transact(&mut self) -> Result<ResultAndState, EVMError<Infallible>> {
32        self.evm.transact()
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use revm_primitives::{InvalidTransaction, U256};
39
40    use super::*;
41
42    #[test]
43    fn coprocessor() {
44        let environment = Environment::builder().build();
45        let mut coprocessor = Coprocessor::new(&environment);
46        coprocessor.evm.tx_mut().value = U256::from(100);
47        let outcome = coprocessor.transact();
48        if let Err(EVMError::Transaction(InvalidTransaction::LackOfFundForMaxFee {
49            fee,
50            balance,
51        })) = outcome
52        {
53            assert_eq!(*fee, U256::from(100));
54            assert_eq!(*balance, U256::from(0));
55        }
56    }
57}