-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
**Motivation** <!-- Why does this pull request exist? What are its goals? --> We currently have an in-memory database that should soon be replaced by the node's in-disk database. For that purpose we want to allow us to switch between both kinds of databases. The need to implement this PR's features and refactor the `Db` arose while working on #904. **Description** <!-- A clear and concise general description of the changes this PR introduces --> This PR includes: - Adding a `Cache` to store warm accounts. This removes the need of having `accessed_accounts` and `accessed_storage_slots` sets in `Substate` because we know that if they are cached then they are warm. - Making our `Db` implement the `Database` trait and interact with it only using methods and not it's attributes, so in the future we can implement that trait for the actual node's database. - Fix call opcodes and remove delegate attribute from `CallFrame`. <!-- Link to issues: Resolves #111, Resolves #222 --> Part of #814. --------- Co-authored-by: Juani Medone <[email protected]> Co-authored-by: maximopalopoli <[email protected]> Co-authored-by: Javier Chatruc <[email protected]>
- Loading branch information
1 parent
acd0365
commit 9c85075
Showing
13 changed files
with
1,239 additions
and
998 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,3 @@ hex = "0.4.3" | |
|
||
[features] | ||
ethereum_foundation_tests = [] | ||
|
||
[profile.test] | ||
opt-level = 3 | ||
debug-assertions = true |
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,3 @@ | ||
## Substate | ||
|
||
`accessed_addresses` and `accessed_storage_keys` follow the structure defined in [EIP 2929](https://eips.ethereum.org/EIPS/eip-2929#specification) |
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
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
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,126 @@ | ||
use crate::vm::{Account, AccountInfo, StorageSlot}; | ||
use ethereum_types::{Address, U256}; | ||
use keccak_hash::H256; | ||
use std::collections::HashMap; | ||
|
||
pub trait Database { | ||
fn get_account_info(&self, address: Address) -> AccountInfo; | ||
fn get_storage_slot(&self, address: Address, key: H256) -> U256; | ||
fn get_block_hash(&self, block_number: u64) -> Option<H256>; | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
pub struct Db { | ||
pub accounts: HashMap<Address, Account>, | ||
pub block_hashes: HashMap<u64, H256>, | ||
} | ||
|
||
// Methods here are for testing purposes only, for initializing the Db with some values | ||
impl Db { | ||
pub fn new() -> Self { | ||
Self { | ||
accounts: HashMap::new(), | ||
block_hashes: HashMap::new(), | ||
} | ||
} | ||
|
||
/// Add accounts to database | ||
pub fn add_accounts(&mut self, accounts: Vec<(Address, Account)>) { | ||
self.accounts.extend(accounts); | ||
} | ||
|
||
/// Add block hashes to database | ||
pub fn add_block_hashes(&mut self, block_hashes: Vec<(u64, H256)>) { | ||
self.block_hashes.extend(block_hashes); | ||
} | ||
|
||
/// Builder method with accounts [for testing only] | ||
pub fn with_accounts(mut self, accounts: HashMap<Address, Account>) -> Self { | ||
self.accounts = accounts; | ||
self | ||
} | ||
|
||
/// Builder method with block hashes [for testing only] | ||
pub fn with_block_hashes(mut self, block_hashes: HashMap<u64, H256>) -> Self { | ||
self.block_hashes = block_hashes; | ||
self | ||
} | ||
} | ||
|
||
impl Database for Db { | ||
fn get_account_info(&self, address: Address) -> AccountInfo { | ||
self.accounts | ||
.get(&address) | ||
.unwrap_or(&Account::default()) | ||
.info | ||
.clone() | ||
} | ||
|
||
fn get_storage_slot(&self, address: Address, key: H256) -> U256 { | ||
// both `original_value` and `current_value` should work here because they have the same values on Db | ||
self.accounts | ||
.get(&address) | ||
.unwrap_or(&Account::default()) | ||
.storage | ||
.get(&key) | ||
.unwrap_or(&StorageSlot::default()) | ||
.original_value | ||
} | ||
|
||
fn get_block_hash(&self, block_number: u64) -> Option<H256> { | ||
self.block_hashes.get(&block_number).cloned() | ||
} | ||
} | ||
|
||
#[derive(Debug, Default, Clone)] | ||
pub struct Cache { | ||
pub accounts: HashMap<Address, Account>, | ||
} | ||
|
||
impl Cache { | ||
pub fn get_account(&self, address: Address) -> Option<&Account> { | ||
self.accounts.get(&address) | ||
} | ||
|
||
pub fn get_mut_account(&mut self, address: Address) -> Option<&mut Account> { | ||
self.accounts.get_mut(&address) | ||
} | ||
|
||
pub fn get_storage_slot(&self, address: Address, key: H256) -> Option<StorageSlot> { | ||
self.get_account(address) | ||
.expect("Account should have been cached") | ||
.storage | ||
.get(&key) | ||
.cloned() | ||
} | ||
|
||
pub fn add_account(&mut self, address: &Address, account: &Account) { | ||
self.accounts.insert(*address, account.clone()); | ||
} | ||
|
||
pub fn write_account_storage(&mut self, address: &Address, key: H256, slot: StorageSlot) { | ||
self.accounts | ||
.get_mut(address) | ||
.expect("Account should have been cached") | ||
.storage | ||
.insert(key, slot); | ||
} | ||
|
||
pub fn increment_account_nonce(&mut self, address: &Address) { | ||
if let Some(account) = self.accounts.get_mut(address) { | ||
account.info.nonce += 1; | ||
} | ||
} | ||
|
||
pub fn is_account_cached(&self, address: &Address) -> bool { | ||
self.accounts.contains_key(address) | ||
} | ||
|
||
pub fn is_slot_cached(&self, address: &Address, key: H256) -> bool { | ||
self.is_account_cached(address) | ||
&& self | ||
.get_account(*address) | ||
.map(|account| account.storage.contains_key(&key)) | ||
.unwrap_or(false) | ||
} | ||
} |
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
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
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
Oops, something went wrong.