Skip to content

Commit

Permalink
feat: environment logs (#911)
Browse files Browse the repository at this point in the history
* feat: logs

* feat: filter on logs

* refactor: `ArbiterDB` and `Environment`
  • Loading branch information
Autoparallel authored Feb 29, 2024
1 parent dbca2d4 commit 16bf32e
Show file tree
Hide file tree
Showing 11 changed files with 415 additions and 191 deletions.
231 changes: 111 additions & 120 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions core/src/database/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ impl ArbiterInspector {
}
}

impl<DB: Database> Inspector<DB> for ArbiterInspector {
impl Inspector<ArbiterDB> for ArbiterInspector {
#[inline]
fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext<DB>) {
fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext<ArbiterDB>) {
if let Some(gas) = &mut self.gas {
gas.initialize_interp(interp, context);
}
}

#[inline]
fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext<DB>) {
fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext<ArbiterDB>) {
if let Some(gas) = &mut self.gas {
gas.step_end(interp, context);
}
Expand All @@ -60,7 +60,7 @@ impl<DB: Database> Inspector<DB> for ArbiterInspector {
#[inline]
fn call(
&mut self,
context: &mut EvmContext<DB>,
context: &mut EvmContext<ArbiterDB>,
inputs: &mut CallInputs,
return_memory_offset: Range<usize>,
) -> Option<CallOutcome> {
Expand All @@ -74,7 +74,7 @@ impl<DB: Database> Inspector<DB> for ArbiterInspector {
#[inline]
fn call_end(
&mut self,
context: &mut EvmContext<DB>,
context: &mut EvmContext<ArbiterDB>,
inputs: &CallInputs,
outcome: CallOutcome,
) -> CallOutcome {
Expand All @@ -88,7 +88,7 @@ impl<DB: Database> Inspector<DB> for ArbiterInspector {
#[inline]
fn create_end(
&mut self,
_context: &mut EvmContext<DB>,
_context: &mut EvmContext<ArbiterDB>,
_inputs: &CreateInputs,
outcome: CreateOutcome,
) -> CreateOutcome {
Expand Down
66 changes: 49 additions & 17 deletions core/src/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,42 @@ use super::*;
pub mod fork;
pub mod inspector;

/// A [`ArbiterDB`] is a wrapper around a [`CacheDB`] that is used to provide
/// access to the [`environment::Environment`]'s database to multiple
/// A [`ArbiterDB`] is contains both a [`CacheDB`] that is used to provide
/// state for the [`environment::Environment`]'s as well as for multiple
/// [`coprocessor::Coprocessor`]s.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ArbiterDB(pub Arc<RwLock<CacheDB<EmptyDB>>>);
/// The `logs` field is a [`HashMap`] to store [`ethers::types::Log`]s that can
/// be queried from at any point.
#[derive(Debug, Serialize, Deserialize)]
pub struct ArbiterDB {
/// The state of the `ArbiterDB`. This is a `CacheDB` that is used to
/// provide a db for the `Environment` to use.
pub state: Arc<RwLock<CacheDB<EmptyDB>>>,

/// The logs of the `ArbiterDB`. This is a `HashMap` that is used to store
/// logs that can be queried from at any point.
pub logs: Arc<RwLock<HashMap<U256, Vec<eLog>>>>,
}

// Implement `Clone` by hand so we utilize the `Arc`'s `Clone` implementation.
impl Clone for ArbiterDB {
fn clone(&self) -> Self {
Self {
state: self.state.clone(),
logs: self.logs.clone(),
}
}
}

impl ArbiterDB {
/// Create a new `ArbiterDB`.
pub fn new() -> Self {
Self(Arc::new(RwLock::new(CacheDB::new(EmptyDB::new()))))
Self {
state: Arc::new(RwLock::new(CacheDB::new(EmptyDB::new()))),
logs: Arc::new(RwLock::new(HashMap::new())),
}
}

/// Write the `ArbiterDB` to a file at the given path.
/// Write the `ArbiterDB` to a file at the given path.``
pub fn write_to_file(&self, path: &str) -> io::Result<()> {
// Serialize the ArbiterDB
let serialized = serde_json::to_string(self)?;
Expand All @@ -49,9 +72,18 @@ impl ArbiterDB {
let mut file = fs::File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;

// Deserialize the content into ArbiterDB
let cache_db = serde_json::from_str(&contents)?;
Ok(Self(Arc::new(RwLock::new(cache_db))))
#[derive(Deserialize)]
struct TempDB {
state: Option<CacheDB<EmptyDB>>,
logs: Option<HashMap<U256, Vec<eLog>>>,
}
let temp_db: TempDB = serde_json::from_str(&contents)?;
Ok(Self {
state: Arc::new(RwLock::new(temp_db.state.unwrap_or_default())),
logs: Arc::new(RwLock::new(temp_db.logs.unwrap_or_default())),
})
}
}

Expand All @@ -77,23 +109,23 @@ impl Database for ArbiterDB {
&mut self,
address: revm::primitives::Address,
) -> Result<Option<AccountInfo>, Self::Error> {
self.0.write().unwrap().basic(address)
self.state.write().unwrap().basic(address)
}

fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
self.0.write().unwrap().code_by_hash(code_hash)
self.state.write().unwrap().code_by_hash(code_hash)
}

fn storage(
&mut self,
address: revm::primitives::Address,
index: U256,
) -> Result<U256, Self::Error> {
self.0.write().unwrap().storage(address, index)
self.state.write().unwrap().storage(address, index)
}

fn block_hash(&mut self, number: U256) -> Result<B256, Self::Error> {
self.0.write().unwrap().block_hash(number)
self.state.write().unwrap().block_hash(number)
}
}

Expand All @@ -104,23 +136,23 @@ impl DatabaseRef for ArbiterDB {
&self,
address: revm::primitives::Address,
) -> Result<Option<AccountInfo>, Self::Error> {
self.0.read().unwrap().basic_ref(address)
self.state.read().unwrap().basic_ref(address)
}

fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
self.0.read().unwrap().code_by_hash_ref(code_hash)
self.state.read().unwrap().code_by_hash_ref(code_hash)
}

fn storage_ref(
&self,
address: revm::primitives::Address,
index: U256,
) -> Result<U256, Self::Error> {
self.0.read().unwrap().storage_ref(address, index)
self.state.read().unwrap().storage_ref(address, index)
}

fn block_hash_ref(&self, number: U256) -> Result<B256, Self::Error> {
self.0.read().unwrap().block_hash_ref(number)
self.state.read().unwrap().block_hash_ref(number)
}
}

Expand All @@ -129,7 +161,7 @@ impl DatabaseCommit for ArbiterDB {
&mut self,
changes: hashbrown::HashMap<revm::primitives::Address, revm::primitives::Account>,
) {
self.0.write().unwrap().commit(changes)
self.state.write().unwrap().commit(changes)
}
}

Expand Down
7 changes: 7 additions & 0 deletions core/src/environment/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ pub(crate) enum Outcome {
/// Currently this may be the block number, block timestamp, gas price, or
/// balance of an account.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub(crate) enum EnvironmentData {
/// The query is for the block number of the [`EVM`].
BlockNumber,
Expand All @@ -161,6 +162,12 @@ pub(crate) enum EnvironmentData {
// TODO: Rename this to `Nonce`?
/// The query is for the nonce of an account given by the inner `Address`.
TransactionCount(eAddress),

/// Query for logs in a range of blocks.
Logs {
/// The filter to use to query for logs
filter: Filter,
},
}

/// [`ReceiptData`] is a structure that holds the block number, transaction
Expand Down
Loading

0 comments on commit 16bf32e

Please sign in to comment.