#pragma once
#include "ethash.h"
#include "hash_types.hpp"
#include <cstdint>
#include <cstring>
#include <memory>
namespace ethash
{
constexpr auto revision = ETHASH_REVISION;
static constexpr int epoch_length = ETHASH_EPOCH_LENGTH;
static constexpr int light_cache_item_size = ETHASH_LIGHT_CACHE_ITEM_SIZE;
static constexpr int full_dataset_item_size = ETHASH_FULL_DATASET_ITEM_SIZE;
static constexpr int num_dataset_accesses = ETHASH_NUM_DATASET_ACCESSES;
using epoch_context = ethash_epoch_context;
using epoch_context_full = ethash_epoch_context_full;
using result = ethash_result;
inline hash256 hash256_from_bytes(const uint8_t bytes[32]) noexcept
{
hash256 h;
std::memcpy(&h, bytes, sizeof(h));
return h;
}
struct search_result
{
bool solution_found = false;
uint64_t nonce = 0;
hash256 final_hash = {};
hash256 mix_hash = {};
search_result() noexcept = default;
search_result(result res, uint64_t n) noexcept
: solution_found(true), nonce(n), final_hash(res.final_hash), mix_hash(res.mix_hash)
{}
};
static constexpr auto calculate_light_cache_num_items = ethash_calculate_light_cache_num_items;
static constexpr auto calculate_full_dataset_num_items = ethash_calculate_full_dataset_num_items;
static constexpr auto calculate_epoch_seed = ethash_calculate_epoch_seed;
inline constexpr int get_epoch_number(int block_number) noexcept
{
return block_number ? block_number / epoch_length : 0;
}
inline constexpr size_t get_light_cache_size(int num_items) noexcept
{
return static_cast<size_t>(num_items) * light_cache_item_size;
}
inline constexpr uint64_t get_full_dataset_size(int num_items) noexcept
{
return static_cast<uint64_t>(num_items) * full_dataset_item_size;
}
using epoch_context_ptr = std::unique_ptr<epoch_context, decltype(ðash_destroy_epoch_context)>;
using epoch_context_full_ptr =
std::unique_ptr<epoch_context_full, decltype(ðash_destroy_epoch_context_full)>;
inline epoch_context_ptr create_epoch_context(int epoch_number) noexcept
{
return {ethash_create_epoch_context(epoch_number), ethash_destroy_epoch_context};
}
inline epoch_context_full_ptr create_epoch_context_full(int epoch_number) noexcept
{
return {ethash_create_epoch_context_full(epoch_number), ethash_destroy_epoch_context_full};
}
inline result hash(
const epoch_context& context, const hash256& header_hash, uint64_t nonce) noexcept
{
return ethash_hash(&context, &header_hash, nonce);
}
result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept;
inline bool verify_final_hash(const hash256& header_hash, const hash256& mix_hash, uint64_t nonce,
const hash256& boundary) noexcept
{
return ethash_verify_final_hash(&header_hash, &mix_hash, nonce, &boundary);
}
inline bool verify(const epoch_context& context, const hash256& header_hash, const hash256& mix_hash,
uint64_t nonce, const hash256& boundary) noexcept
{
return ethash_verify(&context, &header_hash, &mix_hash, nonce, &boundary);
}
search_result search_light(const epoch_context& context, const hash256& header_hash,
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept;
search_result search(const epoch_context_full& context, const hash256& header_hash,
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept;
int find_epoch_number(const hash256& seed) noexcept;
inline const epoch_context& get_global_epoch_context(int epoch_number) noexcept
{
return *ethash_get_global_epoch_context(epoch_number);
}
inline const epoch_context_full& get_global_epoch_context_full(int epoch_number) noexcept
{
return *ethash_get_global_epoch_context_full(epoch_number);
}
}