Skip to content

Commit

Permalink
Separate cleaning state function Use it to properly clean state
Browse files Browse the repository at this point in the history
  • Loading branch information
rodiazet committed Apr 5, 2023
1 parent 5c3155d commit 346d056
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 9 deletions.
18 changes: 9 additions & 9 deletions test/state/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,22 @@ evmc_message build_message(const Transaction& tx, int64_t execution_gas_limit) n
}
} // namespace

void finalize(State& state, evmc_revision rev)
{
std::erase_if(state.get_accounts(), [rev](const std::pair<const address, Account>& p) noexcept {
const auto& acc = p.second;
return acc.destructed || (rev >= EVMC_SPURIOUS_DRAGON && acc.erasable && acc.is_empty());
});
}

std::variant<TransactionReceipt, std::error_code> transition(
State& state, const BlockInfo& block, const Transaction& tx, evmc_revision rev, evmc::VM& vm)
{
auto& sender_acc = state.get(tx.sender);
const auto validation_result = validate_transaction(sender_acc, block, tx, rev);

if (holds_alternative<std::error_code>(validation_result))
{
// Pre EIP-158 coinbase has to be touched also for invalid tx.
if (rev <= EVMC_TANGERINE_WHISTLE)
state.touch(block.coinbase);
return get<std::error_code>(validation_result);
}

const auto execution_gas_limit = get<int64_t>(validation_result);

Expand Down Expand Up @@ -177,10 +180,7 @@ std::variant<TransactionReceipt, std::error_code> transition(
state.touch(block.coinbase).balance += gas_used * priority_gas_price;

// Apply destructs and clear erasable empty accounts.
std::erase_if(state.get_accounts(), [rev](const std::pair<const address, Account>& p) noexcept {
const auto& acc = p.second;
return acc.destructed || (rev >= EVMC_SPURIOUS_DRAGON && acc.erasable && acc.is_empty());
});
finalize(state, rev);

auto receipt = TransactionReceipt{tx.kind, result.status_code, gas_used, host.take_logs(), {}};

Expand Down
3 changes: 3 additions & 0 deletions test/state/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ struct TransactionReceipt
BloomFilter logs_bloom_filter;
};

/// Clears destructed accounts and empty accounts for post EIP158 rev.
void finalize(State& state, evmc_revision rev);

[[nodiscard]] std::variant<TransactionReceipt, std::error_code> transition(
State& state, const BlockInfo& block, const Transaction& tx, evmc_revision rev, evmc::VM& vm);

Expand Down
5 changes: 5 additions & 0 deletions test/statetest/statetest_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ void run_state_test(const StateTransitionTest& test, evmc::VM& vm)
}

const auto res = state::transition(state, test.block, tx, rev, vm);

// Touches coinbase even if block reward is 0. It remains in state pre EIP158.
state.touch(test.block.coinbase);
state::finalize(state, rev);

if (holds_alternative<state::TransactionReceipt>(res))
EXPECT_EQ(logs_hash(get<state::TransactionReceipt>(res).logs), expected.logs_hash);
else
Expand Down
3 changes: 3 additions & 0 deletions test/t8n/t8n.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,12 @@ int main(int argc, const char* argv[])
}
}

// Touches coinbase even if block reward is 0. It remains in state pre EIP158.
if (block_reward.has_value())
state.touch(block.coinbase).balance += *block_reward;

state::finalize(state, rev);

j_result["logsHash"] = hex0x(logs_hash(txs_logs));
j_result["stateRoot"] = hex0x(state::mpt_hash(state.get_accounts()));
}
Expand Down
32 changes: 32 additions & 0 deletions test/unittests/state_rlp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,3 +431,35 @@ TEST(state_rlp, tx_to_rlp_eip1559_with_non_empty_access_list)
EXPECT_EQ(keccak256(rlp::encode(tx)),
0xfb18421827800adcf465688e303cc9863045fdb96971473a114677916a3a08a4_bytes32);
}

TEST(state_rlp, tx_to_rlp_eip2930_with_non_empty_access_list)
{
// https://etherscan.io/tx/0xf076e75aa935552e20e5d9fd4d1dda4ff33399ff3d6ac22843ae646f82c385d4

constexpr std::string_view input = R"({
"input" : "0x095ea7b3000000000000000000000000f17d23136b4fead139f54fb766c8795faae09660ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"gas" : "51253",
"nonce" : "62",
"to" : "0x9232a548dd9e81bac65500b5e0d918f8ba93675c",
"value" : "0",
"v" : "0x1",
"r" : "0x2cfaa5ffa42172bfa9f83207a257c53ba3a106844ee58e9131466f655ecc11e9",
"s" : "0x419366dadd905a16cd433f2953f9ed976560822bb2611ac192b939f7b9c2a98c",
"chainId" : "0x1",
"type" : "0x1",
"gasPrice" : "15650965396",
"accessList" : [
{
"address" : "0x9232a548dd9e81bac65500b5e0d918f8ba93675c",
"storageKeys" : [
"0x8e947fe742892ee6fffe7cfc013acac35d33a3892c58597344bed88b21eb1d2f"
]
}
],
"sender" : "0xcb0b99284784d9e400b1020b01fc40ff193d3540"})";

const auto tx = test::from_json<state::Transaction>(json::json::parse(input));

EXPECT_EQ(keccak256(rlp::encode(tx)),
0xf076e75aa935552e20e5d9fd4d1dda4ff33399ff3d6ac22843ae646f82c385d4_bytes32);
}

0 comments on commit 346d056

Please sign in to comment.