Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: cache block contexts #4815

Merged
merged 9 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,5 @@ Brewfile.lock.json

# Performance profiling application
.clinic

benchmark-scenarios/
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/edr_evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ tokio = { version = "1.21.2", default-features = false, features = ["macros", "r
tracing = { version = "0.1.37", features = ["attributes", "std"], optional = true }

[dev-dependencies]
anyhow = "1.0.75"
criterion = { version = "0.4.0", default-features = false, features = ["cargo_bench_support", "html_reports", "plotters"] }
lazy_static = "1.4.0"
edr_test_utils = { version = "0.2.0-dev", path = "../edr_test_utils" }
Expand Down
34 changes: 16 additions & 18 deletions crates/edr_evm/src/block/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,24 +310,22 @@ impl BlockBuilder {
StateErrorT: Debug + Send,
{
for (address, reward) in rewards {
state.modify_account(
address,
AccountModifierFn::new(Box::new(move |balance, _nonce, _code| {
*balance += reward;
})),
&|| {
Ok(AccountInfo {
code: None,
..AccountInfo::default()
})
},
)?;

let account_info = state
.basic(address)?
.expect("Account must exist after modification");

self.state_diff.apply_account_change(address, account_info);
if reward > U256::ZERO {
let account_info = state.modify_account(
address,
AccountModifierFn::new(Box::new(move |balance, _nonce, _code| {
*balance += reward;
})),
&|| {
Ok(AccountInfo {
code: None,
..AccountInfo::default()
})
},
)?;

self.state_diff.apply_account_change(address, account_info);
}
}

if let Some(gas_limit) = self.parent_gas_limit {
Expand Down
66 changes: 66 additions & 0 deletions crates/edr_evm/src/blockchain/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,69 @@ impl BlockHashRef for LocalBlockchain {
.ok_or(BlockchainError::UnknownBlockNumber)
}
}

#[cfg(test)]
mod tests {
use edr_eth::{AccountInfo, HashMap};
use revm::primitives::{Account, AccountStatus};

use super::*;
use crate::state::IrregularState;

#[test]
fn compute_state_after_reserve() -> anyhow::Result<()> {
let address1 = Address::random();
let accounts = vec![(
address1,
AccountInfo {
balance: U256::from(1_000_000_000u64),
..AccountInfo::default()
},
)];

let genesis_diff = accounts
.iter()
.map(|(address, info)| {
(
*address,
Account {
info: info.clone(),
storage: HashMap::new(),
status: AccountStatus::Created | AccountStatus::Touched,
},
)
})
.collect::<HashMap<_, _>>()
.into();

let mut blockchain = LocalBlockchain::new(
genesis_diff,
123,
SpecId::SHANGHAI,
6_000_000,
None,
Some(B256::random()),
None,
Some(BlobGas::default()),
Some(B256::random()),
)
.unwrap();

let irregular_state = IrregularState::default();
let expected = blockchain.state_at_block_number(0, irregular_state.state_overrides())?;

blockchain.reserve_blocks(1_000_000_000, 1)?;

let actual =
blockchain.state_at_block_number(1_000_000_000, irregular_state.state_overrides())?;

assert_eq!(actual.state_root().unwrap(), expected.state_root().unwrap());

for (address, expected) in accounts {
let actual_account = actual.basic(address)?.expect("account should exist");
assert_eq!(actual_account, expected);
}

Ok(())
}
}
2 changes: 1 addition & 1 deletion crates/edr_evm/src/blockchain/storage/reservable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl<BlockT: Block + Clone> ReservableSparseBlockchainStorage<BlockT> {
previous_base_fee_per_gas: previous_base_fee,
previous_state_root,
previous_total_difficulty,
previous_diff_index: self.state_diffs.len(),
previous_diff_index: self.state_diffs.len() - 1,
spec_id,
};

Expand Down
5 changes: 0 additions & 5 deletions crates/edr_evm/src/upcast.rs

This file was deleted.

1 change: 1 addition & 0 deletions crates/edr_napi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ansi_term = { version = "0.12.1", default-features = false }
crossbeam-channel = { version = "0.5.6", default-features = false }
itertools = { version = "0.12.0", default-features = false }
k256 = { version = "0.13.1", default-features = false, features = ["arithmetic", "ecdsa", "pkcs8", "precomputed-tables", "std"] }
log = { version = "0.4.20", default-features = false }
# when napi is pinned, be sure to pin napi-derive to the same version
# The `async` feature ensures that a tokio runtime is available
napi = { version = "2.12.4", default-features = false, features = ["async", "error_anyhow", "napi8", "serde-json"] }
Expand Down
14 changes: 6 additions & 8 deletions crates/edr_napi/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,12 @@ impl Provider {
if let Some((method_name, provider_error)) = reason.provider_error() {
// Ignore potential failure of logging, as returning the original error is more
// important
let _result = runtime::Handle::current()
.spawn_blocking(move || {
provider.log_failed_deserialization(&method_name, &provider_error)
})
if let Err(error) = provider
.log_failed_deserialization(&method_name, &provider_error)
.await
.map_err(|error| {
napi::Error::new(Status::GenericFailure, error.to_string())
})?;
{
log::error!("Failed to log deserialization error: {error}");
}
}

let data = serde_json::from_str(&json_request).ok();
Expand All @@ -107,7 +105,7 @@ impl Provider {
};

let response = runtime::Handle::current()
.spawn_blocking(move || provider.handle_request(request))
.spawn(async move { provider.handle_request(request).await })
.await
.map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?;

Expand Down
1 change: 1 addition & 0 deletions crates/edr_provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ sha3 = { version = "0.10.6", default-features = false }
thiserror = { version = "1.0.37", default-features = false }
tokio = { version = "1.21.2", default-features = false, features = ["macros"] }
tracing = { version = "0.1.37", features = ["attributes", "std"] }
lru = "0.12.2"

[dev-dependencies]
anyhow = "1.0.75"
Expand Down
13 changes: 8 additions & 5 deletions crates/edr_provider/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ impl IntervalConfig {
}
}

impl From<OneUsizeOrTwo> for IntervalConfig {
fn from(value: OneUsizeOrTwo) -> Self {
impl TryFrom<OneUsizeOrTwo> for IntervalConfig {
type Error = ();

fn try_from(value: OneUsizeOrTwo) -> Result<Self, Self::Error> {
match value {
OneUsizeOrTwo::One(value) => Self::Fixed(value as u64),
OneUsizeOrTwo::Two([min, max]) => Self::Range {
OneUsizeOrTwo::One(0) => Err(()),
OneUsizeOrTwo::One(value) => Ok(Self::Fixed(value as u64)),
OneUsizeOrTwo::Two([min, max]) => Ok(Self::Range {
min: min as u64,
max: max as u64,
},
}),
}
}
}
Expand Down
Loading
Loading