Skip to content

Commit ffd7390

Browse files
committed
test: Generalize validate_state() (#795)
Generalize `validate_deployed_code()` to `validate_state()`. It validates an Ethereum state (likely a test pre-state). New added check: disallow zero-value storage entries.
1 parent c4886ee commit ffd7390

File tree

6 files changed

+41
-24
lines changed

6 files changed

+41
-24
lines changed

test/statetest/statetest.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,11 @@ json::json to_json(const std::unordered_map<address, state::Account>& accounts);
9595

9696
StateTransitionTest load_state_test(std::istream& input);
9797

98-
/// Validates deployed EOF containers before running state test.
99-
/// Throws exception on any invalid EOF in state.
100-
void validate_deployed_code(const state::State& state, evmc_revision rev);
98+
/// Validates an Ethereum state:
99+
/// - checks that there are no zero-value storage entries,
100+
/// - checks that there are no invalid EOF codes.
101+
/// Throws std::invalid_argument exception.
102+
void validate_state(const state::State& state, evmc_revision rev);
101103

102104
/// Execute the state @p test using the @p vm.
103105
///

test/statetest/statetest_loader.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,9 @@ state::State from_json<state::State>(const json::json& j)
271271
{
272272
for (const auto& [j_key, j_value] : storage_it->items())
273273
{
274-
const auto value = from_json<bytes32>(j_value);
275-
acc.storage.insert(
276-
{from_json<bytes32>(j_key), {.current = value, .original = value}});
274+
if (const auto value = from_json<bytes32>(j_value); !is_zero(value))
275+
acc.storage.insert(
276+
{from_json<bytes32>(j_key), {.current = value, .original = value}});
277277
}
278278
}
279279
}
@@ -434,10 +434,12 @@ StateTransitionTest load_state_test(std::istream& input)
434434
return json::json::parse(input).get<StateTransitionTest>();
435435
}
436436

437-
void validate_deployed_code(const state::State& state, evmc_revision rev)
437+
void validate_state(const state::State& state, evmc_revision rev)
438438
{
439439
for (const auto& [addr, acc] : state.get_accounts())
440440
{
441+
// TODO: Check for empty accounts after Paris.
442+
// https://github.com/ethereum/tests/issues/1331
441443
if (is_eof_container(acc.code))
442444
{
443445
if (rev >= EVMC_PRAGUE)
@@ -451,6 +453,16 @@ void validate_deployed_code(const state::State& state, evmc_revision rev)
451453
}
452454
}
453455
}
456+
457+
for (const auto& [key, value] : acc.storage)
458+
{
459+
if (is_zero(value.original))
460+
{
461+
throw std::invalid_argument{"account " + hex0x(addr) +
462+
" contains invalid zero-value storage entry " +
463+
hex0x(key)};
464+
}
465+
}
454466
}
455467
}
456468
} // namespace evmone::test

test/statetest/statetest_runner.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ void run_state_test(const StateTransitionTest& test, evmc::VM& vm, bool trace_su
1313
{
1414
for (const auto& [rev, cases] : test.cases)
1515
{
16+
validate_state(test.pre_state, rev);
1617
for (size_t case_index = 0; case_index != cases.size(); ++case_index)
1718
{
1819
SCOPED_TRACE(std::string{evmc::to_string(rev)} + '/' + std::to_string(case_index));
@@ -25,8 +26,6 @@ void run_state_test(const StateTransitionTest& test, evmc::VM& vm, bool trace_su
2526
const auto tx = test.multi_tx.get(expected.indexes);
2627
auto state = test.pre_state;
2728

28-
validate_deployed_code(state, rev);
29-
3029
const auto res = state::transition(state, test.block, tx, rev, vm, test.block.gas_limit,
3130
state::BlockInfo::MAX_BLOB_GAS_PER_BLOCK);
3231

test/t8n/t8n.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,19 +112,17 @@ int main(int argc, const char* argv[])
112112
std::vector<state::TransactionReceipt> receipts;
113113
int64_t block_gas_left = block.gas_limit;
114114

115-
// Validate eof code in pre-state
116-
if (rev >= EVMC_PRAGUE)
117-
validate_deployed_code(state, rev);
115+
validate_state(state, rev);
118116

119117
// Parse and execute transactions
120118
if (!txs_file.empty())
121119
{
122120
const auto j_txs = json::json::parse(std::ifstream{txs_file});
123121

124-
evmc::VM vm{evmc_create_evmone(), {{"O", "0"}}};
122+
evmc::VM vm{evmc_create_evmone()};
125123

126124
if (trace)
127-
vm.set_option("trace", "0");
125+
vm.set_option("trace", "1");
128126

129127
std::vector<state::Log> txs_logs;
130128

test/unittests/state_transition.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,7 @@ class TraceCapture
4040

4141
void state_transition::TearDown()
4242
{
43-
for (const auto& [addr, acc] : pre.get_accounts())
44-
{
45-
if (is_eof_container(acc.code))
46-
{
47-
ASSERT_EQ(validate_eof(rev, acc.code), EOFValidationError::success)
48-
<< "invalid EOF in prestate at " << addr;
49-
}
50-
}
43+
validate_state(pre, rev);
5144

5245
auto state = pre;
5346
const auto trace = !expect.trace.empty();

test/unittests/statetest_loader_test.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,27 @@ TEST(statetest_loader, load_minimal_test)
133133
EXPECT_EQ(st.input_labels.size(), 0);
134134
}
135135

136-
TEST(statetest_loader, validate_deployed_code_test)
136+
TEST(statetest_loader, validate_state_invalid_eof)
137137
{
138138
{
139139
state::State state;
140140
state.insert(0xadd4_address, {.code = "EF0001010000020001000103000100FEDA"_hex});
141-
EXPECT_THAT([&] { validate_deployed_code(state, EVMC_PRAGUE); },
141+
EXPECT_THAT([&] { validate_state(state, EVMC_PRAGUE); },
142142
ThrowsMessage<std::invalid_argument>(
143143
"EOF container at 0x000000000000000000000000000000000000add4 is invalid: "
144144
"zero_section_size"));
145145
}
146146
}
147+
148+
TEST(statetest_loader, validate_state_zero_storage_slot)
149+
{
150+
{
151+
state::State state;
152+
state.insert(0xadd4_address, {.storage = {{0x01_bytes32, {0x00_bytes32}}}});
153+
EXPECT_THAT([&] { validate_state(state, EVMC_PRAGUE); },
154+
ThrowsMessage<std::invalid_argument>(
155+
"account 0x000000000000000000000000000000000000add4 contains invalid zero-value "
156+
"storage entry "
157+
"0x0000000000000000000000000000000000000000000000000000000000000001"));
158+
}
159+
}

0 commit comments

Comments
 (0)