Skip to content

Commit 44da532

Browse files
agostbiroWodann
andauthored
fix: cache block contexts (#4815)
Co-authored-by: Wodann <[email protected]>
1 parent f0f5ca6 commit 44da532

File tree

27 files changed

+511
-212
lines changed

27 files changed

+511
-212
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,5 @@ Brewfile.lock.json
111111

112112
# Performance profiling application
113113
.clinic
114+
115+
benchmark-scenarios/

Cargo.lock

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/edr_evm/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ tokio = { version = "1.21.2", default-features = false, features = ["macros", "r
3030
tracing = { version = "0.1.37", features = ["attributes", "std"], optional = true }
3131

3232
[dev-dependencies]
33+
anyhow = "1.0.75"
3334
criterion = { version = "0.4.0", default-features = false, features = ["cargo_bench_support", "html_reports", "plotters"] }
3435
lazy_static = "1.4.0"
3536
edr_test_utils = { version = "0.2.0-dev", path = "../edr_test_utils" }

crates/edr_evm/src/block/builder.rs

+16-18
Original file line numberDiff line numberDiff line change
@@ -310,24 +310,22 @@ impl BlockBuilder {
310310
StateErrorT: Debug + Send,
311311
{
312312
for (address, reward) in rewards {
313-
state.modify_account(
314-
address,
315-
AccountModifierFn::new(Box::new(move |balance, _nonce, _code| {
316-
*balance += reward;
317-
})),
318-
&|| {
319-
Ok(AccountInfo {
320-
code: None,
321-
..AccountInfo::default()
322-
})
323-
},
324-
)?;
325-
326-
let account_info = state
327-
.basic(address)?
328-
.expect("Account must exist after modification");
329-
330-
self.state_diff.apply_account_change(address, account_info);
313+
if reward > U256::ZERO {
314+
let account_info = state.modify_account(
315+
address,
316+
AccountModifierFn::new(Box::new(move |balance, _nonce, _code| {
317+
*balance += reward;
318+
})),
319+
&|| {
320+
Ok(AccountInfo {
321+
code: None,
322+
..AccountInfo::default()
323+
})
324+
},
325+
)?;
326+
327+
self.state_diff.apply_account_change(address, account_info);
328+
}
331329
}
332330

333331
if let Some(gas_limit) = self.parent_gas_limit {

crates/edr_evm/src/blockchain/local.rs

+66
Original file line numberDiff line numberDiff line change
@@ -395,3 +395,69 @@ impl BlockHashRef for LocalBlockchain {
395395
.ok_or(BlockchainError::UnknownBlockNumber)
396396
}
397397
}
398+
399+
#[cfg(test)]
400+
mod tests {
401+
use edr_eth::{AccountInfo, HashMap};
402+
use revm::primitives::{Account, AccountStatus};
403+
404+
use super::*;
405+
use crate::state::IrregularState;
406+
407+
#[test]
408+
fn compute_state_after_reserve() -> anyhow::Result<()> {
409+
let address1 = Address::random();
410+
let accounts = vec![(
411+
address1,
412+
AccountInfo {
413+
balance: U256::from(1_000_000_000u64),
414+
..AccountInfo::default()
415+
},
416+
)];
417+
418+
let genesis_diff = accounts
419+
.iter()
420+
.map(|(address, info)| {
421+
(
422+
*address,
423+
Account {
424+
info: info.clone(),
425+
storage: HashMap::new(),
426+
status: AccountStatus::Created | AccountStatus::Touched,
427+
},
428+
)
429+
})
430+
.collect::<HashMap<_, _>>()
431+
.into();
432+
433+
let mut blockchain = LocalBlockchain::new(
434+
genesis_diff,
435+
123,
436+
SpecId::SHANGHAI,
437+
6_000_000,
438+
None,
439+
Some(B256::random()),
440+
None,
441+
Some(BlobGas::default()),
442+
Some(B256::random()),
443+
)
444+
.unwrap();
445+
446+
let irregular_state = IrregularState::default();
447+
let expected = blockchain.state_at_block_number(0, irregular_state.state_overrides())?;
448+
449+
blockchain.reserve_blocks(1_000_000_000, 1)?;
450+
451+
let actual =
452+
blockchain.state_at_block_number(1_000_000_000, irregular_state.state_overrides())?;
453+
454+
assert_eq!(actual.state_root().unwrap(), expected.state_root().unwrap());
455+
456+
for (address, expected) in accounts {
457+
let actual_account = actual.basic(address)?.expect("account should exist");
458+
assert_eq!(actual_account, expected);
459+
}
460+
461+
Ok(())
462+
}
463+
}

crates/edr_evm/src/blockchain/storage/reservable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl<BlockT: Block + Clone> ReservableSparseBlockchainStorage<BlockT> {
150150
previous_base_fee_per_gas: previous_base_fee,
151151
previous_state_root,
152152
previous_total_difficulty,
153-
previous_diff_index: self.state_diffs.len(),
153+
previous_diff_index: self.state_diffs.len() - 1,
154154
spec_id,
155155
};
156156

crates/edr_evm/src/upcast.rs

-5
This file was deleted.

crates/edr_napi/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ansi_term = { version = "0.12.1", default-features = false }
1111
crossbeam-channel = { version = "0.5.6", default-features = false }
1212
itertools = { version = "0.12.0", default-features = false }
1313
k256 = { version = "0.13.1", default-features = false, features = ["arithmetic", "ecdsa", "pkcs8", "precomputed-tables", "std"] }
14+
log = { version = "0.4.20", default-features = false }
1415
# when napi is pinned, be sure to pin napi-derive to the same version
1516
# The `async` feature ensures that a tokio runtime is available
1617
napi = { version = "2.12.4", default-features = false, features = ["async", "error_anyhow", "napi8", "serde-json"] }

crates/edr_napi/src/provider.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,12 @@ impl Provider {
7373
if let Some((method_name, provider_error)) = reason.provider_error() {
7474
// Ignore potential failure of logging, as returning the original error is more
7575
// important
76-
let _result = runtime::Handle::current()
77-
.spawn_blocking(move || {
78-
provider.log_failed_deserialization(&method_name, &provider_error)
79-
})
76+
if let Err(error) = provider
77+
.log_failed_deserialization(&method_name, &provider_error)
8078
.await
81-
.map_err(|error| {
82-
napi::Error::new(Status::GenericFailure, error.to_string())
83-
})?;
79+
{
80+
log::error!("Failed to log deserialization error: {error}");
81+
}
8482
}
8583

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

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

crates/edr_provider/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ sha3 = { version = "0.10.6", default-features = false }
2323
thiserror = { version = "1.0.37", default-features = false }
2424
tokio = { version = "1.21.2", default-features = false, features = ["macros"] }
2525
tracing = { version = "0.1.37", features = ["attributes", "std"] }
26+
lru = "0.12.2"
2627

2728
[dev-dependencies]
2829
anyhow = "1.0.75"

crates/edr_provider/src/config.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@ impl IntervalConfig {
2525
}
2626
}
2727

28-
impl From<OneUsizeOrTwo> for IntervalConfig {
29-
fn from(value: OneUsizeOrTwo) -> Self {
28+
impl TryFrom<OneUsizeOrTwo> for IntervalConfig {
29+
type Error = ();
30+
31+
fn try_from(value: OneUsizeOrTwo) -> Result<Self, Self::Error> {
3032
match value {
31-
OneUsizeOrTwo::One(value) => Self::Fixed(value as u64),
32-
OneUsizeOrTwo::Two([min, max]) => Self::Range {
33+
OneUsizeOrTwo::One(0) => Err(()),
34+
OneUsizeOrTwo::One(value) => Ok(Self::Fixed(value as u64)),
35+
OneUsizeOrTwo::Two([min, max]) => Ok(Self::Range {
3336
min: min as u64,
3437
max: max as u64,
35-
},
38+
}),
3639
}
3740
}
3841
}

0 commit comments

Comments
 (0)