Skip to content

Commit

Permalink
fix(anvil): set storage.best_hash while loading state (#9021)
Browse files Browse the repository at this point in the history
* fix(anvil): set `storage.best_hash` while loading state

* clippy nit

* test: strengthen can_load_state
  • Loading branch information
yash-atreya authored Oct 3, 2024
1 parent a355af4 commit 67018dc
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
21 changes: 16 additions & 5 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,14 +800,28 @@ impl Backend {

/// Apply [SerializableState] data to the backend storage.
pub async fn load_state(&self, state: SerializableState) -> Result<bool, BlockchainError> {
// load the blocks and transactions into the storage
self.blockchain.storage.write().load_blocks(state.blocks.clone());
self.blockchain.storage.write().load_transactions(state.transactions.clone());
// reset the block env
if let Some(block) = state.block.clone() {
self.env.write().block = block.clone();

// Set the current best block number.
// Defaults to block number for compatibility with existing state files.
self.blockchain.storage.write().best_number =
state.best_block_number.unwrap_or(block.number.to::<U64>());

let best_number = state.best_block_number.unwrap_or(block.number.to::<U64>());
self.blockchain.storage.write().best_number = best_number;

// Set the current best block hash;
let best_hash =
self.blockchain.storage.read().hash(best_number.into()).ok_or_else(|| {
BlockchainError::RpcError(RpcError::internal_error_with(format!(
"Best hash not found for best number {best_number}",
)))
})?;

self.blockchain.storage.write().best_hash = best_hash;
}

if !self.db.write().await.load_state(state.clone())? {
Expand All @@ -817,9 +831,6 @@ impl Backend {
.into());
}

self.blockchain.storage.write().load_blocks(state.blocks.clone());
self.blockchain.storage.write().load_transactions(state.transactions.clone());

if let Some(historical_states) = state.historical_states {
self.states.write().load_states(historical_states);
}
Expand Down
15 changes: 14 additions & 1 deletion crates/anvil/tests/it/state.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! general eth api tests

use crate::abi::Greeter;
use alloy_primitives::{Bytes, Uint};
use alloy_primitives::{Bytes, Uint, U256};
use alloy_provider::Provider;
use alloy_rpc_types::BlockId;
use anvil::{spawn, NodeConfig};
Expand All @@ -13,6 +13,7 @@ async fn can_load_state() {

let (api, _handle) = spawn(NodeConfig::test()).await;

api.mine_one().await;
api.mine_one().await;

let num = api.block_number().unwrap();
Expand All @@ -23,7 +24,19 @@ async fn can_load_state() {
let (api, _handle) = spawn(NodeConfig::test().with_init_state_path(state_file)).await;

let num2 = api.block_number().unwrap();

// Ref: https://github.com/foundry-rs/foundry/issues/9017
// Check responses of eth_blockNumber and eth_getBlockByNumber don't deviate after loading state
let num_from_tag = api
.block_by_number(alloy_eips::BlockNumberOrTag::Latest)
.await
.unwrap()
.unwrap()
.header
.number;
assert_eq!(num, num2);

assert_eq!(num, U256::from(num_from_tag));
}

#[tokio::test(flavor = "multi_thread")]
Expand Down

0 comments on commit 67018dc

Please sign in to comment.