Skip to content

Commit

Permalink
state: Introduce difficulty calculation in t8n
Browse files Browse the repository at this point in the history
  • Loading branch information
rodiazet committed Aug 22, 2023
1 parent 0944d94 commit 2c54f0c
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 10 deletions.
2 changes: 2 additions & 0 deletions test/state/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ target_sources(
bloom_filter.hpp
bloom_filter.cpp
errors.hpp
ethash_difficulty.hpp
ethash_difficulty.cpp
hash_utils.hpp
hash_utils.cpp
host.hpp
Expand Down
64 changes: 64 additions & 0 deletions test/state/ethash_difficulty.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "ethash_difficulty.hpp"
#include "hash_utils.hpp"
#include "mpt_hash.hpp"
#include <evmc/evmc.h>
#include <intx/intx.hpp>
#include <stdexcept>

using namespace evmone;

namespace evmone::state
{
namespace
{
int64_t get_bomb_delay(evmc_revision rev)
{
switch (rev)
{
case EVMC_BYZANTIUM:
return 3000000;
case EVMC_CONSTANTINOPLE:
case EVMC_PETERSBURG:
case EVMC_ISTANBUL:
return 5000000;
case EVMC_BERLIN:
return 9000000;
case EVMC_LONDON:
return 9700000;
default:
throw std::runtime_error("get_bomb_delay: Wrong rev");
}
}
} // namespace

int64_t calc_difficulty(const int64_t& parent_difficulty, const hash256& parent_uncle_hash,
const int64_t& parent_timestamp, const int64_t& current_timestamp, const int64_t& block_num,
evmc_revision rev)
{
if (rev >= EVMC_PARIS)
return 0;

// TODO: Implement for older revisions
if (rev < EVMC_BYZANTIUM)
return 0x020000;

static constexpr auto min_difficulty = int64_t{1} << 17;

const auto kappa = get_bomb_delay(rev);

const auto H_i_prime = kappa >= block_num ? 0 : block_num - kappa;

const auto p = (H_i_prime / 100000) - 2;
assert(p < 63);

const auto epsilon = p < 0 ? 0 : int64_t{1} << p;

const auto y = parent_uncle_hash != state::EmptyListHash ? 2 : 1;

const auto sigma_2 = std::max(y - (current_timestamp - parent_timestamp) / 9, int64_t{-99});

const int64_t x = parent_difficulty / 2048;

return std::max(min_difficulty, (int64_t)parent_difficulty + x * sigma_2 + epsilon);
}
} // namespace evmone::state
14 changes: 14 additions & 0 deletions test/state/ethash_difficulty.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2023 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0
#pragma once

#include "hash_utils.hpp"
#include <evmc/evmc.h>

namespace evmone::state
{
int64_t calc_difficulty(const int64_t& parent_difficulty, const hash256& parent_uncle_hash,
const int64_t& parent_timestamp, const int64_t& current_timestamp, const int64_t& block_num,
evmc_revision rev);
} // namespace evmone::state
3 changes: 3 additions & 0 deletions test/state/mpt_hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

namespace evmone::state
{
static constexpr auto EmptyListHash =
0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347_bytes32;

struct Account;
struct Transaction;
struct TransactionReceipt;
Expand Down
4 changes: 4 additions & 0 deletions test/state/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ struct BlockInfo
{
int64_t number = 0;
int64_t timestamp = 0;
int64_t parent_timestamp = 0;
int64_t gas_limit = 0;
address coinbase;
int64_t current_difficulty = 0;
int64_t parent_difficulty = 0;
hash256 parent_uncle_hash = {};
bytes32 prev_randao;
uint64_t base_fee = 0;
std::vector<Withdrawal> withdrawals;
Expand Down
33 changes: 26 additions & 7 deletions test/statetest/statetest_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,30 @@ inline uint64_t calculate_current_base_fee_eip1559(
template <>
state::BlockInfo from_json<state::BlockInfo>(const json::json& j)
{
evmc::bytes32 difficulty;
evmc::bytes32 prev_randao;
int64_t current_difficulty = 0;
int64_t parent_difficulty = 0;
const auto prev_randao_it = j.find("currentRandom");
const auto current_difficulty_it = j.find("currentDifficulty");
const auto parent_difficulty_it = j.find("parentDifficulty");

if (current_difficulty_it != j.end())
current_difficulty = from_json<int64_t>(*current_difficulty_it);
if (parent_difficulty_it != j.end())
parent_difficulty = from_json<int64_t>(*parent_difficulty_it);

// When it's not defined init it with difficulty value.
if (prev_randao_it != j.end())
difficulty = from_json<bytes32>(*prev_randao_it);
prev_randao = from_json<bytes32>(*prev_randao_it);
else if (current_difficulty_it != j.end())
difficulty = from_json<bytes32>(*current_difficulty_it);
prev_randao = from_json<bytes32>(*current_difficulty_it);
else if (parent_difficulty_it != j.end())
difficulty = from_json<bytes32>(*parent_difficulty_it);
prev_randao = from_json<bytes32>(*parent_difficulty_it);

hash256 parent_uncle_hash;
const auto parent_uncle_hash_it = j.find("parentUncleHash");
if (parent_uncle_hash_it != j.end())
parent_uncle_hash = from_json<hash256>(*parent_uncle_hash_it);

uint64_t base_fee = 0;
if (j.contains("currentBaseFee"))
Expand Down Expand Up @@ -191,10 +205,15 @@ state::BlockInfo from_json<state::BlockInfo>(const json::json& j)
}
}

int64_t parent_timestamp = 0;
auto parent_timestamp_it = j.find("parentTimestamp");
if (parent_timestamp_it != j.end())
parent_timestamp = from_json<int64_t>(*parent_timestamp_it);

return {from_json<int64_t>(j.at("currentNumber")), from_json<int64_t>(j.at("currentTimestamp")),
from_json<int64_t>(j.at("currentGasLimit")),
from_json<evmc::address>(j.at("currentCoinbase")), difficulty, base_fee,
std::move(withdrawals), std::move(ommers)};
parent_timestamp, from_json<int64_t>(j.at("currentGasLimit")),
from_json<evmc::address>(j.at("currentCoinbase")), current_difficulty, parent_difficulty,
parent_uncle_hash, prev_randao, base_fee, std::move(withdrawals), std::move(ommers)};
}

template <>
Expand Down
33 changes: 31 additions & 2 deletions test/t8n/t8n.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: Apache-2.0

#include "../state/errors.hpp"
#include "../state/ethash_difficulty.hpp"
#include "../state/mpt_hash.hpp"
#include "../state/rlp.hpp"
#include "../statetest/statetest.hpp"
Expand Down Expand Up @@ -81,8 +82,36 @@ int main(int argc, const char* argv[])
}

json::json j_result;
// FIXME: Calculate difficulty properly
j_result["currentDifficulty"] = "0x20000";

// Difficulty was received from upstream. No need to calc
// TODO: Check is it's needed by the blockchain test. If not remove if statement true branch
if (block.current_difficulty != 0)
j_result["currentDifficulty"] = hex0x(block.current_difficulty);
else
{
if (rev >= EVMC_SHANGHAI)
j_result["currentDifficulty"] = nullptr;
else
{
const auto current_difficulty =
state::calc_difficulty(block.parent_difficulty, block.parent_uncle_hash,
block.parent_timestamp, block.timestamp, block.number, rev);

j_result["currentDifficulty"] = hex0x(current_difficulty);
block.current_difficulty = current_difficulty;

// Override prev_randao with difficulty (swap bytes to BE) pre Merge
if (rev < EVMC_PARIS)
{
std::memset(block.prev_randao.bytes, 0, 32);
const auto s = sizeof(current_difficulty);
const auto diff_ptr = reinterpret_cast<const uint8_t*>(&current_difficulty);
for (size_t i = 0; i < s; ++i)
block.prev_randao.bytes[24 + i] = diff_ptr[s - 1 - i];
}
}
};

j_result["currentBaseFee"] = hex0x(block.base_fee);

int64_t cumulative_gas_used = 0;
Expand Down
3 changes: 2 additions & 1 deletion test/unittests/statetest_loader_block_info_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ TEST(statetest_loader, block_info_0_parent_difficulty)
"parentBaseFee": "7",
"parentGasUsed": "0",
"parentGasLimit": "100000000000000000",
"parentTimstamp": "0",
"parentTimestamp": "253",
"blockHashes": {
"0": "0xc305d826e3784046a7e9d31128ef98d3e96133fe454c16ef630574d967dfdb1a"
},
Expand All @@ -147,6 +147,7 @@ TEST(statetest_loader, block_info_0_parent_difficulty)
EXPECT_EQ(bi.base_fee, 7);
EXPECT_EQ(bi.timestamp, 1000);
EXPECT_EQ(bi.number, 1);
EXPECT_EQ(bi.parent_timestamp, 253);
}

TEST(statetest_loader, block_info_0_random)
Expand Down

0 comments on commit 2c54f0c

Please sign in to comment.