Skip to content
Open
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
4 changes: 2 additions & 2 deletions test/state/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 24 additions & 6 deletions test/state/ethash_difficulty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
// Copyright 2023 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0


#include "ethash_difficulty.hpp"
#include <algorithm>
#include <cassert>


namespace evmone::state
{
namespace
Expand All @@ -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<int64_t>(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);
Expand All @@ -61,31 +73,37 @@ 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<int64_t>(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(
parent_difficulty, parent_timestamp, current_timestamp, block_number, rev) :
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
2 changes: 1 addition & 1 deletion test/state/ethash_difficulty.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 4 additions & 4 deletions test/utils/statetest_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,9 @@ state::BlockInfo from_json_with_rev(

return state::BlockInfo{
.number = from_json<int64_t>(j.at("currentNumber")),
.timestamp = from_json<int64_t>(j.at("currentTimestamp")),
.parent_timestamp = load_or<int64_t>(j, "parentTimestamp", 0),
.gas_limit = from_json<int64_t>(j.at("currentGasLimit")),
.timestamp = from_json<uint64_t>(j.at("currentTimestamp")),
.parent_timestamp = load_or<uint64_t>(j, "parentTimestamp", 0),
.parent_timestamp = load_or<uint64_t>(j, "parentTimestamp", 0),
.coinbase = from_json<evmc::address>(j.at("currentCoinbase")),
.difficulty = load_or<int64_t>(j, "currentDifficulty", 0),
.parent_difficulty = load_or<int64_t>(j, "parentDifficulty", 0),
Expand Down Expand Up @@ -328,7 +328,7 @@ TestState from_json<TestState>(const json::json& j)
acc.storage[from_json<bytes32>(j_key)] = value;
}
}
}
// Block timestamps are loaded as uint64_t to preserve the full EVM range.
return o;
}

Expand Down