Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: EIP-6780: SELFDESTRUCT only in same transaction #1620

Merged
merged 9 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 9 additions & 33 deletions cmd/test/ethereum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,6 @@ static const std::vector<fs::path> kSlowTests{
// TODO(yperbasis) make them pass
static const std::vector<fs::path> kFailingTests{
kBlockchainDir / "cancun" / "eip4844_blobs",
kBlockchainDir / "cancun" / "eip5656_mcopy",
kBlockchainDir / "cancun" / "eip6780_selfdestruct",
};

// TODO(yperbasis) remove me
static const std::vector<fs::path> kSkipCancunTests{
kBlockchainDir / "frontier",
kBlockchainDir / "homestead",
kBlockchainDir / "istanbul",
kBlockchainDir / "merge",
kBlockchainDir / "shanghai",
};

static constexpr size_t kColumnWidth{80};
Expand Down Expand Up @@ -129,8 +118,8 @@ Status run_block(const nlohmann::json& json_block, Blockchain& blockchain) {
}

bool post_check(const InMemoryState& state, const nlohmann::json& expected) {
if (state.number_of_accounts() != expected.size()) {
std::cout << "Account number mismatch: " << state.number_of_accounts() << " != " << expected.size()
if (state.accounts().size() != expected.size()) {
std::cout << "Account number mismatch: " << state.accounts().size() << " != " << expected.size()
<< std::endl;
return false;
}
Expand Down Expand Up @@ -219,11 +208,8 @@ struct [[nodiscard]] RunResults {
};

// https://ethereum-tests.readthedocs.io/en/latest/test_types/blockchain_tests.html
RunResults blockchain_test(const nlohmann::json& json_test, bool skip_cancun) {
RunResults blockchain_test(const nlohmann::json& json_test) {
const auto network{json_test["network"].get<std::string>()};
if (skip_cancun && network == "Cancun") {
return Status::kSkipped;
}
const auto config_it{test::kNetworkConfig.find(network)};
if (config_it == test::kNetworkConfig.end()) {
std::cout << "unknown network " << network << std::endl;
Expand Down Expand Up @@ -287,9 +273,9 @@ std::atomic<size_t> total_passed{0};
std::atomic<size_t> total_failed{0};
std::atomic<size_t> total_skipped{0};

using RunnerFunc = RunResults (*)(const nlohmann::json&, bool skip_cancun);
using RunnerFunc = RunResults (*)(const nlohmann::json&);

void run_test_file(const fs::path& file_path, RunnerFunc runner, bool skip_cancun) {
void run_test_file(const fs::path& file_path, RunnerFunc runner) {
std::ifstream in{file_path.string()};
nlohmann::json json;

Expand All @@ -305,7 +291,7 @@ void run_test_file(const fs::path& file_path, RunnerFunc runner, bool skip_cancu
RunResults total;

for (const auto& test : json.items()) {
const RunResults r{runner(test.value(), skip_cancun)};
const RunResults r{runner(test.value())};
total += r;
if (r.failed || r.skipped) {
print_test_status(test.key(), r);
Expand All @@ -318,7 +304,7 @@ void run_test_file(const fs::path& file_path, RunnerFunc runner, bool skip_cancu
}

// https://ethereum-tests.readthedocs.io/en/latest/test_types/transaction_tests.html
RunResults transaction_test(const nlohmann::json& j, bool) {
RunResults transaction_test(const nlohmann::json& j) {
Transaction txn;
bool decoded{false};

Expand Down Expand Up @@ -434,7 +420,7 @@ Status individual_difficulty_test(const nlohmann::json& j, const ChainConfig& co
}
}

RunResults difficulty_tests(const nlohmann::json& outer, bool) {
RunResults difficulty_tests(const nlohmann::json& outer) {
RunResults res;

for (const auto& network : outer.items()) {
Expand All @@ -459,15 +445,6 @@ bool exclude_test(const fs::path& p, const fs::path& root_dir, bool include_slow
(!include_slow_tests && as_range::any_of(kSlowTests, path_fits));
}

bool skip_cancun(const fs::path& p, const fs::path& root_dir) {
for (const fs::path& e : kSkipCancunTests) {
if (p.string().starts_with((root_dir / e).string())) {
return true;
}
}
return false;
}

int main(int argc, char* argv[]) {
StopWatch sw;
sw.start();
Expand Down Expand Up @@ -525,8 +502,7 @@ int main(int argc, char* argv[]) {
i.disable_recursion_pending();
} else if (fs::is_regular_file(i->path()) && i->path().extension() == ".json") {
const fs::path path{*i};
const bool no_cancun{skip_cancun(path, root_dir)};
thread_pool.push_task([=]() { run_test_file(path, runner, no_cancun); });
thread_pool.push_task([=]() { run_test_file(path, runner); });
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions silkworm/core/execution/evm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,15 @@ size_t EvmHost::copy_code(const evmc::address& address, size_t code_offset, uint
}

bool EvmHost::selfdestruct(const evmc::address& address, const evmc::address& beneficiary) noexcept {
const bool recorded{evm_.state().record_suicide(address)};
evm_.state().add_to_balance(beneficiary, evm_.state().get_balance(address));
evm_.state().set_balance(address, 0);
return recorded;
const intx::uint256 balance{evm_.state().get_balance(address)};
evm_.state().add_to_balance(beneficiary, balance);
if (evm_.revision() >= EVMC_CANCUN && !evm_.state().created().contains(address)) {
evm_.state().subtract_from_balance(address, balance);
return false;
} else {
evm_.state().set_balance(address, 0);
return evm_.state().record_suicide(address);
}
}

evmc::Result EvmHost::call(const evmc_message& message) noexcept {
Expand Down
2 changes: 1 addition & 1 deletion silkworm/core/protocol/param.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ inline constexpr uint64_t kBlobGasPriceUpdateFraction{3338477};
// EIP-4788: Beacon block root in the EVM
inline constexpr uint64_t kSystemCallGasLimit{30'000'000};
inline constexpr auto kSystemAddress{0xfffffffffffffffffffffffffffffffffffffffe_address};
inline constexpr auto kBeaconRootsAddress{0x0b_address}; // TODO(yperbasis) change to the proper one
inline constexpr auto kBeaconRootsAddress{0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02_address};

// Used in Bor & Clique
inline constexpr size_t kExtraSealSize{65};
Expand Down
2 changes: 0 additions & 2 deletions silkworm/core/state/in_memory_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,6 @@ void InMemoryState::unwind_state_changes(BlockNum block_number) {
}
}

size_t InMemoryState::number_of_accounts() const { return accounts_.size(); }

size_t InMemoryState::storage_size(const evmc::address& address, uint64_t incarnation) const {
const auto it1{storage_.find(address)};
if (it1 != storage_.end()) {
Expand Down
1 change: 0 additions & 1 deletion silkworm/core/state/in_memory_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ class InMemoryState : public State {

void unwind_state_changes(BlockNum block_number) override;

size_t number_of_accounts() const;
const FlatHashMap<BlockNum, AccountChanges>& account_changes() const { return account_changes_; }
const FlatHashMap<evmc::address, Account>& accounts() const { return accounts_; }

Expand Down
6 changes: 2 additions & 4 deletions silkworm/core/state/intra_block_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ bool IntraBlockState::is_dead(const evmc::address& address) const noexcept {
}

void IntraBlockState::create_contract(const evmc::address& address) noexcept {
created_.insert(address);
state::Object created{};
created.current = Account{};

Expand Down Expand Up @@ -172,10 +173,6 @@ void IntraBlockState::add_to_balance(const evmc::address& address, const intx::u

void IntraBlockState::subtract_from_balance(const evmc::address& address, const intx::uint256& subtrahend) noexcept {
auto& obj{get_or_create_object(address)};
if (subtrahend == 0) {
// See https://github.com/ethereum/go-ethereum/blob/v1.13.0/core/state/state_object.go#L419
return;
}
journal_.emplace_back(new state::UpdateBalanceDelta{address, obj.current->balance});
obj.current->balance -= subtrahend;
touch(address);
Expand Down Expand Up @@ -385,6 +382,7 @@ void IntraBlockState::clear_journal_and_substate() {
self_destructs_.clear();
logs_.clear();
touched_.clear();
created_.clear();
// EIP-2929
accessed_addresses_.clear();
accessed_storage_keys_.clear();
Expand Down
3 changes: 3 additions & 0 deletions silkworm/core/state/intra_block_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ class IntraBlockState {

const FlatHashSet<evmc::address>& touched() const noexcept { return touched_; }

const FlatHashSet<evmc::address>& created() const noexcept { return created_; }

evmc::bytes32 get_transient_storage(const evmc::address& address, const evmc::bytes32& key);

void set_transient_storage(const evmc::address& addr, const evmc::bytes32& key, const evmc::bytes32& value);
Expand Down Expand Up @@ -151,6 +153,7 @@ class IntraBlockState {
FlatHashSet<evmc::address> self_destructs_;
std::vector<Log> logs_;
FlatHashSet<evmc::address> touched_;
FlatHashSet<evmc::address> created_; // required for EIP-6780
// EIP-2929 substate
FlatHashSet<evmc::address> accessed_addresses_;
FlatHashMap<evmc::address, FlatHashSet<evmc::bytes32>> accessed_storage_keys_;
Expand Down
2 changes: 0 additions & 2 deletions silkworm/wasm/silkworm_wasm_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,6 @@ static evmc::address address_from_ptr(const uint8_t* ptr) { return bytes_to_addr

static evmc::bytes32 bytes32_from_ptr(const uint8_t* ptr) { return to_bytes32({ptr, kHashLength}); }

size_t state_number_of_accounts(const InMemoryState* state) { return state->number_of_accounts(); }

size_t state_storage_size(const InMemoryState* state, const uint8_t* address, const Account* account) {
return state->storage_size(address_from_ptr(address), account->incarnation);
}
Expand Down
2 changes: 0 additions & 2 deletions silkworm/wasm/silkworm_wasm_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ SILKWORM_EXPORT void block_recover_senders(silkworm::Block* b);
SILKWORM_EXPORT silkworm::InMemoryState* new_state();
SILKWORM_EXPORT void delete_state(silkworm::InMemoryState* x);

SILKWORM_EXPORT size_t state_number_of_accounts(const silkworm::InMemoryState* state);

SILKWORM_EXPORT size_t state_storage_size(const silkworm::InMemoryState* state, const uint8_t* address,
const silkworm::Account* account);

Expand Down
Loading