2015-02-28 19:58:37 +00:00
|
|
|
#pragma once
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "endian.h"
|
|
|
|
#include "ethash.h"
|
2015-05-05 05:50:04 +00:00
|
|
|
#include <stdio.h>
|
2015-02-28 19:58:37 +00:00
|
|
|
|
2015-03-14 15:42:05 +00:00
|
|
|
#define ENABLE_SSE 0
|
2015-02-28 19:58:37 +00:00
|
|
|
|
|
|
|
#if defined(_M_X64) && ENABLE_SSE
|
|
|
|
#include <smmintrin.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// compile time settings
|
|
|
|
#define NODE_WORDS (64/4)
|
2015-05-05 05:50:04 +00:00
|
|
|
#define MIX_WORDS (ETHASH_MIX_BYTES/4)
|
2015-02-28 19:58:37 +00:00
|
|
|
#define MIX_NODES (MIX_WORDS / NODE_WORDS)
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
typedef union node {
|
2015-05-05 05:50:04 +00:00
|
|
|
uint8_t bytes[NODE_WORDS * 4];
|
|
|
|
uint32_t words[NODE_WORDS];
|
|
|
|
uint64_t double_words[NODE_WORDS / 2];
|
2015-02-28 19:58:37 +00:00
|
|
|
|
|
|
|
#if defined(_M_X64) && ENABLE_SSE
|
|
|
|
__m128i xmm[NODE_WORDS/4];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} node;
|
|
|
|
|
2015-05-05 05:50:04 +00:00
|
|
|
static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i)
|
|
|
|
{
|
|
|
|
return hash->b[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ethash_h256_set(ethash_h256_t* hash, unsigned int i, uint8_t v)
|
|
|
|
{
|
|
|
|
hash->b[i] = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ethash_h256_reset(ethash_h256_t* hash)
|
|
|
|
{
|
|
|
|
memset(hash, 0, 32);
|
|
|
|
}
|
|
|
|
|
2015-06-24 05:17:21 +00:00
|
|
|
// Returns if hash is less than or equal to boundary (2^256/difficulty)
|
2015-05-07 17:39:55 +00:00
|
|
|
static inline bool ethash_check_difficulty(
|
2015-05-05 05:50:04 +00:00
|
|
|
ethash_h256_t const* hash,
|
2015-06-24 05:17:21 +00:00
|
|
|
ethash_h256_t const* boundary
|
2015-05-05 05:50:04 +00:00
|
|
|
)
|
|
|
|
{
|
2015-06-24 05:17:21 +00:00
|
|
|
// Boundary is big endian
|
2015-05-05 05:50:04 +00:00
|
|
|
for (int i = 0; i < 32; i++) {
|
2015-06-24 05:17:21 +00:00
|
|
|
if (ethash_h256_get(hash, i) == ethash_h256_get(boundary, i)) {
|
2015-05-05 05:50:04 +00:00
|
|
|
continue;
|
|
|
|
}
|
2015-06-24 05:17:21 +00:00
|
|
|
return ethash_h256_get(hash, i) < ethash_h256_get(boundary, i);
|
2015-05-05 05:50:04 +00:00
|
|
|
}
|
2015-05-07 17:39:55 +00:00
|
|
|
return true;
|
2015-05-05 05:50:04 +00:00
|
|
|
}
|
|
|
|
|
2015-06-24 05:17:21 +00:00
|
|
|
/**
|
|
|
|
* Difficulty quick check for POW preverification
|
|
|
|
*
|
|
|
|
* @param header_hash The hash of the header
|
|
|
|
* @param nonce The block's nonce
|
|
|
|
* @param mix_hash The mix digest hash
|
|
|
|
* @param boundary The boundary is defined as (2^256 / difficulty)
|
|
|
|
* @return true for succesful pre-verification and false otherwise
|
|
|
|
*/
|
2015-05-07 17:39:55 +00:00
|
|
|
bool ethash_quick_check_difficulty(
|
2015-05-05 05:50:04 +00:00
|
|
|
ethash_h256_t const* header_hash,
|
|
|
|
uint64_t const nonce,
|
|
|
|
ethash_h256_t const* mix_hash,
|
2015-06-24 05:17:21 +00:00
|
|
|
ethash_h256_t const* boundary
|
2015-05-05 05:50:04 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
struct ethash_light {
|
|
|
|
void* cache;
|
|
|
|
uint64_t cache_size;
|
|
|
|
uint64_t block_number;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate and initialize a new ethash_light handler. Internal version
|
|
|
|
*
|
|
|
|
* @param cache_size The size of the cache in bytes
|
|
|
|
* @param seed Block seedhash to be used during the computation of the
|
|
|
|
* cache nodes
|
|
|
|
* @return Newly allocated ethash_light handler or NULL in case of
|
|
|
|
* ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
|
|
|
|
*/
|
|
|
|
ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate the light client data. Internal version.
|
|
|
|
*
|
|
|
|
* @param light The light client handler
|
|
|
|
* @param full_size The size of the full data in bytes.
|
|
|
|
* @param header_hash The header hash to pack into the mix
|
|
|
|
* @param nonce The nonce to pack into the mix
|
|
|
|
* @return The resulting hash.
|
|
|
|
*/
|
|
|
|
ethash_return_value_t ethash_light_compute_internal(
|
|
|
|
ethash_light_t light,
|
|
|
|
uint64_t full_size,
|
|
|
|
ethash_h256_t const header_hash,
|
|
|
|
uint64_t nonce
|
|
|
|
);
|
|
|
|
|
|
|
|
struct ethash_full {
|
|
|
|
FILE* file;
|
|
|
|
uint64_t file_size;
|
|
|
|
node* data;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate and initialize a new ethash_full handler. Internal version.
|
|
|
|
*
|
|
|
|
* @param dirname The directory in which to put the DAG file.
|
|
|
|
* @param seedhash The seed hash of the block. Used in the DAG file naming.
|
|
|
|
* @param full_size The size of the full data in bytes.
|
|
|
|
* @param cache A cache object to use that was allocated with @ref ethash_cache_new().
|
|
|
|
* Iff this function succeeds the ethash_full_t will take memory
|
|
|
|
* memory ownership of the cache and free it at deletion. If
|
|
|
|
* not then the user still has to handle freeing of the cache himself.
|
|
|
|
* @param callback A callback function with signature of @ref ethash_callback_t
|
|
|
|
* It accepts an unsigned with which a progress of DAG calculation
|
|
|
|
* can be displayed. If all goes well the callback should return 0.
|
|
|
|
* If a non-zero value is returned then DAG generation will stop.
|
|
|
|
* @return Newly allocated ethash_full handler or NULL in case of
|
|
|
|
* ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
|
|
|
|
*/
|
|
|
|
ethash_full_t ethash_full_new_internal(
|
|
|
|
char const* dirname,
|
|
|
|
ethash_h256_t const seed_hash,
|
|
|
|
uint64_t full_size,
|
|
|
|
ethash_light_t const light,
|
|
|
|
ethash_callback_t callback
|
|
|
|
);
|
|
|
|
|
|
|
|
void ethash_calculate_dag_item(
|
|
|
|
node* const ret,
|
|
|
|
uint32_t node_index,
|
|
|
|
ethash_light_t const cache
|
|
|
|
);
|
|
|
|
|
|
|
|
void ethash_quick_hash(
|
|
|
|
ethash_h256_t* return_hash,
|
|
|
|
ethash_h256_t const* header_hash,
|
|
|
|
const uint64_t nonce,
|
|
|
|
ethash_h256_t const* mix_hash
|
|
|
|
);
|
|
|
|
|
|
|
|
uint64_t ethash_get_datasize(uint64_t const block_number);
|
|
|
|
uint64_t ethash_get_cachesize(uint64_t const block_number);
|
2015-04-07 11:17:27 +00:00
|
|
|
|
2015-05-05 05:50:04 +00:00
|
|
|
/**
|
|
|
|
* Compute the memory data for a full node's memory
|
|
|
|
*
|
|
|
|
* @param mem A pointer to an ethash full's memory
|
|
|
|
* @param full_size The size of the full data in bytes
|
|
|
|
* @param cache A cache object to use in the calculation
|
|
|
|
* @param callback The callback function. Check @ref ethash_full_new() for details.
|
|
|
|
* @return true if all went fine and false for invalid parameters
|
|
|
|
*/
|
|
|
|
bool ethash_compute_full_data(
|
|
|
|
void* mem,
|
|
|
|
uint64_t full_size,
|
|
|
|
ethash_light_t const light,
|
|
|
|
ethash_callback_t callback
|
|
|
|
);
|
2015-02-28 19:58:37 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
2015-04-07 11:17:27 +00:00
|
|
|
#endif
|