Breaking changes (#5191)

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>
Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com>
Co-authored-by: joshieDo <ranriver@protonmail.com>
Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
Co-authored-by: Oliver Nordbjerg <hi@notbjerg.me>
Co-authored-by: Thomas Coratger <thomas.coratger@gmail.com>
This commit is contained in:
Alexey Shekhirin
2024-02-29 12:37:28 +00:00
committed by GitHub
parent 025fa5f038
commit 6b5b6f7a40
252 changed files with 10154 additions and 6327 deletions

View File

@ -17,7 +17,7 @@ ef-tests = []
[dependencies]
reth-primitives.workspace = true
reth-db = { workspace = true, features = ["mdbx", "test-utils"] }
reth-provider.workspace = true
reth-provider = { workspace = true, features = ["test-utils"] }
reth-stages.workspace = true
reth-interfaces.workspace = true
reth-revm.workspace = true
@ -29,3 +29,4 @@ walkdir = "2.3.3"
serde = "1.0.163"
serde_json.workspace = true
thiserror.workspace = true
rayon.workspace = true

View File

@ -5,10 +5,11 @@ use crate::{
Case, Error, Suite,
};
use alloy_rlp::Decodable;
use reth_db::test_utils::create_test_rw_db;
use rayon::iter::{ParallelBridge, ParallelIterator};
use reth_db::test_utils::{create_test_rw_db, create_test_static_files_dir};
use reth_node_ethereum::EthEvmConfig;
use reth_primitives::{BlockBody, SealedBlock};
use reth_provider::{BlockWriter, HashingWriter, ProviderFactory};
use reth_primitives::{BlockBody, SealedBlock, StaticFileSegment};
use reth_provider::{providers::StaticFileWriter, HashingWriter, ProviderFactory};
use reth_stages::{stages::ExecutionStage, ExecInput, Stage};
use std::{collections::BTreeMap, fs, path::Path, sync::Arc};
@ -64,83 +65,107 @@ impl Case for BlockchainTestCase {
}
// Iterate through test cases, filtering by the network type to exclude specific forks.
for case in self.tests.values().filter(|case| {
!matches!(
case.network,
ForkSpec::ByzantiumToConstantinopleAt5 |
ForkSpec::Constantinople |
ForkSpec::ConstantinopleFix |
ForkSpec::MergeEOF |
ForkSpec::MergeMeterInitCode |
ForkSpec::MergePush0 |
ForkSpec::Unknown
)
}) {
// Create a new test database and initialize a provider for the test case.
let db = create_test_rw_db();
let provider = ProviderFactory::new(db.as_ref(), Arc::new(case.network.clone().into()))
self.tests
.values()
.filter(|case| {
!matches!(
case.network,
ForkSpec::ByzantiumToConstantinopleAt5 |
ForkSpec::Constantinople |
ForkSpec::ConstantinopleFix |
ForkSpec::MergeEOF |
ForkSpec::MergeMeterInitCode |
ForkSpec::MergePush0 |
ForkSpec::Unknown
)
})
.par_bridge()
.try_for_each(|case| {
// Create a new test database and initialize a provider for the test case.
let db = create_test_rw_db();
let static_files_dir = create_test_static_files_dir();
let provider = ProviderFactory::new(
db.as_ref(),
Arc::new(case.network.clone().into()),
static_files_dir.clone(),
)?
.provider_rw()
.unwrap();
// Insert initial test state into the provider.
provider
.insert_block(
SealedBlock::new(
case.genesis_block_header.clone().into(),
BlockBody::default(),
)
.try_seal_with_senders()
.unwrap(),
None,
)
.map_err(|err| Error::RethError(err.into()))?;
case.pre.write_to_db(provider.tx_ref())?;
// Decode and insert blocks, creating a chain of blocks for the test case.
let last_block = case.blocks.iter().try_fold(None, |_, block| {
let decoded = SealedBlock::decode(&mut block.rlp.as_ref())?;
// Insert initial test state into the provider.
provider
.insert_block(decoded.clone().try_seal_with_senders().unwrap(), None)
.insert_historical_block(
SealedBlock::new(
case.genesis_block_header.clone().into(),
BlockBody::default(),
)
.try_seal_with_senders()
.unwrap(),
None,
)
.map_err(|err| Error::RethError(err.into()))?;
Ok::<Option<SealedBlock>, Error>(Some(decoded))
})?;
case.pre.write_to_db(provider.tx_ref())?;
// Execute the execution stage using the EVM processor factory for the test case
// network.
let _ = ExecutionStage::new_with_factory(reth_revm::EvmProcessorFactory::new(
Arc::new(case.network.clone().into()),
EthEvmConfig::default(),
))
.execute(
&provider,
ExecInput { target: last_block.as_ref().map(|b| b.number), checkpoint: None },
);
// Validate the post-state for the test case.
match (&case.post_state, &case.post_state_hash) {
(Some(state), None) => {
// Validate accounts in the state against the provider's database.
for (&address, account) in state.iter() {
account.assert_db(address, provider.tx_ref())?;
}
}
(None, Some(expected_state_root)) => {
// Insert state hashes into the provider based on the expected state root.
let last_block = last_block.unwrap_or_default();
// Decode and insert blocks, creating a chain of blocks for the test case.
let last_block = case.blocks.iter().try_fold(None, |_, block| {
let decoded = SealedBlock::decode(&mut block.rlp.as_ref())?;
provider
.insert_hashes(
0..=last_block.number,
last_block.hash(),
*expected_state_root,
.insert_historical_block(
decoded.clone().try_seal_with_senders().unwrap(),
None,
)
.map_err(|err| Error::RethError(err.into()))?;
}
_ => return Err(Error::MissingPostState),
}
Ok::<Option<SealedBlock>, Error>(Some(decoded))
})?;
provider
.static_file_provider()
.latest_writer(StaticFileSegment::Headers)
.unwrap()
.commit()
.unwrap();
// Drop the provider without committing to the database.
drop(provider);
}
// Execute the execution stage using the EVM processor factory for the test case
// network.
let _ = ExecutionStage::new_with_factory(reth_revm::EvmProcessorFactory::new(
Arc::new(case.network.clone().into()),
EthEvmConfig::default(),
))
.execute(
&provider,
ExecInput { target: last_block.as_ref().map(|b| b.number), checkpoint: None },
);
// Validate the post-state for the test case.
match (&case.post_state, &case.post_state_hash) {
(Some(state), None) => {
// Validate accounts in the state against the provider's database.
for (&address, account) in state.iter() {
account.assert_db(address, provider.tx_ref())?;
}
}
(None, Some(expected_state_root)) => {
// Insert state hashes into the provider based on the expected state root.
let last_block = last_block.unwrap_or_default();
provider
.insert_hashes(
0..=last_block.number,
last_block.hash(),
*expected_state_root,
)
.map_err(|err| Error::RethError(err.into()))?;
}
_ => return Err(Error::MissingPostState),
}
// Drop the provider without committing to the database.
drop(provider);
// TODO: replace with `tempdir` usage, so the temp directory is removed
// automatically when the variable goes out of scope
reth_primitives::fs::remove_dir_all(static_files_dir)
.expect("Failed to remove static files directory");
Ok(())
})?;
Ok(())
}

View File

@ -161,7 +161,7 @@ impl State {
bytecode_hash: code_hash,
};
tx.put::<tables::PlainAccountState>(address, reth_account)?;
tx.put::<tables::HashedAccount>(hashed_address, reth_account)?;
tx.put::<tables::HashedAccounts>(hashed_address, reth_account)?;
if let Some(code_hash) = code_hash {
tx.put::<tables::Bytecodes>(code_hash, Bytecode::new_raw(account.code.clone()))?;
}
@ -171,7 +171,7 @@ impl State {
address,
StorageEntry { key: storage_key, value: *v },
)?;
tx.put::<tables::HashedStorage>(
tx.put::<tables::HashedStorages>(
hashed_address,
StorageEntry { key: keccak256(storage_key), value: *v },
)