Skip to content

Commit 14ae941

Browse files
committed
blockchaintest: Optional partial state hash check
This is blockchain tests execution optimization: for listed test names only check state root hash of first 5 blocks (to detect early problems) and last 5 blocks (to do the final check of the chain of blocks). The current implementation of the MPT hash of the state builds the trie from scratch (no updates to the trie of the previous block). For the tests will a long chain of blocks the performance degrades significantly with 99% time spent in the keccak hash function. This improves testing of EIP-2935 implemented in #953.
1 parent a79218c commit 14ae941

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

test/blockchaintest/blockchaintest_runner.cpp

+28-3
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,33 @@ std::string print_state(const TestState& s)
116116

117117
return out.str();
118118
}
119+
120+
/// How many first/last state hashes to check in the series of block for the "partial" check.
121+
constexpr size_t PARTIAL_STATE_HASH_CHECK_MARGIN = 5;
122+
123+
/// List of test names for which only perform the partial state root hash checks.
124+
/// For tests on the list, only check state hashes for first M (early problems)
125+
/// and last M (final check of the chain) blocks,
126+
/// where M is defined by PARTIAL_STATE_HASH_CHECK_MARGIN.
127+
/// Otherwise, for very long blockchain test we spend a lot of time in MPT hashing
128+
/// because the implementation of it is very simplistic: the trie is not updated
129+
/// along the state changes but a new trie is build from scratch for every block.
130+
constexpr std::array PARTIAL_STATE_HASH_CHECK_TESTS{
131+
"a test name",
132+
};
133+
134+
119135
} // namespace
120136

121137
void run_blockchain_tests(std::span<const BlockchainTest> tests, evmc::VM& vm)
122138
{
123139
for (size_t case_index = 0; case_index != tests.size(); ++case_index)
124140
{
125141
const auto& c = tests[case_index];
142+
143+
const bool partial_state_hash_check = std::ranges::find(PARTIAL_STATE_HASH_CHECK_TESTS,
144+
c.name) != PARTIAL_STATE_HASH_CHECK_TESTS.end();
145+
126146
SCOPED_TRACE(std::string{evmc::to_string(c.rev.get_revision(0))} + '/' +
127147
std::to_string(case_index) + '/' + c.name);
128148

@@ -142,8 +162,9 @@ void run_blockchain_tests(std::span<const BlockchainTest> tests, evmc::VM& vm)
142162
std::unordered_map<int64_t, hash256> known_block_hashes{
143163
{c.genesis_block_header.block_number, c.genesis_block_header.hash}};
144164

145-
for (const auto& test_block : c.test_blocks)
165+
for (size_t block_idx = 0; block_idx != c.test_blocks.size(); ++block_idx)
146166
{
167+
const auto& test_block = c.test_blocks[block_idx];
147168
auto bi = test_block.block_info;
148169
bi.known_block_hashes = known_block_hashes;
149170

@@ -158,8 +179,12 @@ void run_blockchain_tests(std::span<const BlockchainTest> tests, evmc::VM& vm)
158179
SCOPED_TRACE(std::string{evmc::to_string(rev)} + '/' + std::to_string(case_index) +
159180
'/' + c.name + '/' + std::to_string(test_block.block_info.number));
160181

161-
EXPECT_EQ(
162-
state::mpt_hash(TestState{state}), test_block.expected_block_header.state_root);
182+
if (!partial_state_hash_check || block_idx < PARTIAL_STATE_HASH_CHECK_MARGIN ||
183+
block_idx >= c.test_blocks.size() - PARTIAL_STATE_HASH_CHECK_MARGIN)
184+
{
185+
EXPECT_EQ(
186+
state::mpt_hash(TestState{state}), test_block.expected_block_header.state_root);
187+
}
163188

164189
if (rev >= EVMC_SHANGHAI)
165190
{

0 commit comments

Comments
 (0)