diff --git a/test/state/block.hpp b/test/state/block.hpp index 295f98956e..1027935d8f 100644 --- a/test/state/block.hpp +++ b/test/state/block.hpp @@ -34,10 +34,10 @@ struct Withdrawal struct BlockInfo { int64_t number = 0; - int64_t timestamp = 0; + uint64_t timestamp = 0; hash256 hash; hash256 parent_hash; - int64_t parent_timestamp = 0; + uint64_t parent_timestamp = 0; int64_t gas_limit = 0; int64_t gas_used = 0; address coinbase; diff --git a/test/state/ethash_difficulty.cpp b/test/state/ethash_difficulty.cpp index 31254f2fb8..e888d6f86a 100644 --- a/test/state/ethash_difficulty.cpp +++ b/test/state/ethash_difficulty.cpp @@ -2,10 +2,12 @@ // Copyright 2023 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 + #include "ethash_difficulty.hpp" #include #include + namespace evmone::state { namespace @@ -28,30 +30,40 @@ int64_t get_bomb_delay(evmc_revision rev) noexcept } } -int64_t calculate_difficulty_pre_byzantium(int64_t parent_difficulty, int64_t parent_timestamp, - int64_t current_timestamp, int64_t block_number, evmc_revision rev) + +int64_t calculate_difficulty_pre_byzantium(int64_t parent_difficulty, uint64_t parent_timestamp, + uint64_t current_timestamp, int64_t block_number, evmc_revision rev) { // According to https://eips.ethereum.org/EIPS/eip-2 const auto period_count = block_number / 100'000; const auto offset = parent_difficulty / 2048; + auto diff = parent_difficulty; + if (rev < EVMC_HOMESTEAD) diff += offset * (current_timestamp - parent_timestamp < 13 ? 1 : -1); else - diff += offset * std::max(1 - (current_timestamp - parent_timestamp) / 10, int64_t{-99}); + { + const auto timestamp_delta = (current_timestamp - parent_timestamp) / 10; + diff += offset * (timestamp_delta > 100 ? int64_t{-99} : + std::max(1 - static_cast(timestamp_delta), int64_t{-99})); + } + if (period_count > 2) diff += 2 << (block_number / 100'000 - 3); else if (period_count == 2) diff += 1; + return diff; } + int64_t calculate_difficulty_since_byzantium(int64_t parent_difficulty, bool parent_has_ommers, - int64_t parent_timestamp, int64_t current_timestamp, int64_t block_number, + uint64_t parent_timestamp, uint64_t current_timestamp, int64_t block_number, evmc_revision rev) noexcept { const auto delay = get_bomb_delay(rev); @@ -61,24 +73,29 @@ int64_t calculate_difficulty_since_byzantium(int64_t parent_difficulty, bool par const auto epsilon = p < 0 ? 0 : int64_t{1} << p; const auto y = parent_has_ommers ? 2 : 1; + const auto timestamp_diff = current_timestamp - parent_timestamp; assert(timestamp_diff > 0); - const auto sigma_2 = std::max(y - timestamp_diff / 9, int64_t{-99}); + const auto sigma_2 = timestamp_diff / 9 >= 100 ? int64_t{-99} : + std::max(y - static_cast(timestamp_diff / 9), int64_t{-99}); const auto x = parent_difficulty / 2048; return parent_difficulty + x * sigma_2 + epsilon; } } // namespace + int64_t calculate_difficulty(int64_t parent_difficulty, bool parent_has_ommers, - int64_t parent_timestamp, int64_t current_timestamp, int64_t block_number, + uint64_t parent_timestamp, uint64_t current_timestamp, int64_t block_number, evmc_revision rev) noexcept { // The calculation follows Ethereum Yellow Paper section 4.3.4. "Block Header Validity". static constexpr int64_t MIN_DIFFICULTY = 0x20000; + if (rev >= EVMC_PARIS) return 0; // No difficulty after the Merge. + const auto difficulty = (rev < EVMC_BYZANTIUM) ? calculate_difficulty_pre_byzantium( @@ -86,6 +103,7 @@ int64_t calculate_difficulty(int64_t parent_difficulty, bool parent_has_ommers, calculate_difficulty_since_byzantium(parent_difficulty, parent_has_ommers, parent_timestamp, current_timestamp, block_number, rev); + return std::max(MIN_DIFFICULTY, difficulty); } } // namespace evmone::state diff --git a/test/state/ethash_difficulty.hpp b/test/state/ethash_difficulty.hpp index a271cc2a22..408fbab73f 100644 --- a/test/state/ethash_difficulty.hpp +++ b/test/state/ethash_difficulty.hpp @@ -8,6 +8,6 @@ namespace evmone::state { int64_t calculate_difficulty(int64_t parent_difficulty, bool parent_has_ommers, - int64_t parent_timestamp, int64_t current_timestamp, int64_t block_number, + uint64_t parent_timestamp, uint64_t current_timestamp, int64_t block_number, evmc_revision rev) noexcept; } // namespace evmone::state diff --git a/test/utils/statetest_loader.cpp b/test/utils/statetest_loader.cpp index 2d282e54d7..cfb42b6f71 100644 --- a/test/utils/statetest_loader.cpp +++ b/test/utils/statetest_loader.cpp @@ -277,9 +277,9 @@ state::BlockInfo from_json_with_rev( return state::BlockInfo{ .number = from_json(j.at("currentNumber")), - .timestamp = from_json(j.at("currentTimestamp")), - .parent_timestamp = load_or(j, "parentTimestamp", 0), - .gas_limit = from_json(j.at("currentGasLimit")), + .timestamp = from_json(j.at("currentTimestamp")), + .parent_timestamp = load_or(j, "parentTimestamp", 0), + .parent_timestamp = load_or(j, "parentTimestamp", 0), .coinbase = from_json(j.at("currentCoinbase")), .difficulty = load_or(j, "currentDifficulty", 0), .parent_difficulty = load_or(j, "parentDifficulty", 0), @@ -328,7 +328,7 @@ TestState from_json(const json::json& j) acc.storage[from_json(j_key)] = value; } } - } + // Block timestamps are loaded as uint64_t to preserve the full EVM range. return o; }