mirror of
https://github.com/JayDDee/cpuminer-opt.git
synced 2025-09-17 23:44:27 +00:00
v3.16.0
This commit is contained in:
@@ -129,7 +129,7 @@ cpuminer_SOURCES = \
|
||||
algo/lyra2/allium.c \
|
||||
algo/lyra2/phi2-4way.c \
|
||||
algo/lyra2/phi2.c \
|
||||
algo//m7m/m7m.c \
|
||||
algo/m7m/m7m.c \
|
||||
algo/m7m/magimath.cpp \
|
||||
algo/nist5/nist5-gate.c \
|
||||
algo/nist5/nist5-4way.c \
|
||||
@@ -192,6 +192,10 @@ cpuminer_SOURCES = \
|
||||
algo/sm3/sm3-hash-4way.c \
|
||||
algo/swifftx/swifftx.c \
|
||||
algo/tiger/sph_tiger.c \
|
||||
algo/verthash/verthash-gate.c \
|
||||
algo/verthash/Verthash.c \
|
||||
algo/verthash/fopen_utf8.c \
|
||||
algo/verthash/tiny_sha3/sha3.c \
|
||||
algo/whirlpool/sph_whirlpool.c \
|
||||
algo/whirlpool/whirlpool-hash-4way.c \
|
||||
algo/whirlpool/whirlpool-gate.c \
|
||||
|
@@ -65,6 +65,10 @@ If not what makes it happen or not happen?
|
||||
Change Log
|
||||
----------
|
||||
|
||||
v3.16.0
|
||||
|
||||
Added verthash algo.
|
||||
|
||||
v3.15.7
|
||||
|
||||
Added accepted/stale/rejected percentage to summary log report.
|
||||
|
@@ -349,6 +349,7 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
|
||||
case ALGO_TRIBUS: register_tribus_algo ( gate ); break;
|
||||
case ALGO_VANILLA: register_vanilla_algo ( gate ); break;
|
||||
case ALGO_VELTOR: register_veltor_algo ( gate ); break;
|
||||
case ALGO_VERTHASH: register_verthash_algo ( gate ); break;
|
||||
case ALGO_WHIRLPOOL: register_whirlpool_algo ( gate ); break;
|
||||
case ALGO_WHIRLPOOLX: register_whirlpoolx_algo ( gate ); break;
|
||||
case ALGO_X11: register_x11_algo ( gate ); break;
|
||||
|
@@ -691,6 +691,14 @@ sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
|
||||
// sph_sha256_init(cc);
|
||||
}
|
||||
|
||||
void sph_sha256_full( void *dst, const void *data, size_t len )
|
||||
{
|
||||
sph_sha256_context cc;
|
||||
sph_sha256_init( &cc );
|
||||
sph_sha256( &cc, data, len );
|
||||
sph_sha256_close( &cc, dst );
|
||||
}
|
||||
|
||||
/* see sph_sha2.h */
|
||||
//void
|
||||
//sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8])
|
||||
|
@@ -205,6 +205,10 @@ void sph_sha256_comp(const sph_u32 msg[16], sph_u32 val[8]);
|
||||
#define sph_sha256_comp sph_sha224_comp
|
||||
#endif
|
||||
|
||||
void sph_sha256_full( void *dst, const void *data, size_t len );
|
||||
|
||||
|
||||
|
||||
#if SPH_64
|
||||
|
||||
/**
|
||||
|
BIN
algo/verthash/.verthash-gate.c.swp
Normal file
BIN
algo/verthash/.verthash-gate.c.swp
Normal file
Binary file not shown.
621
algo/verthash/Verthash.c
Normal file
621
algo/verthash/Verthash.c
Normal file
@@ -0,0 +1,621 @@
|
||||
/*
|
||||
* Copyright 2018-2021 CryptoGraphics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version. See LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "Verthash.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Verthash info management
|
||||
int verthash_info_init(verthash_info_t* info, const char* file_name)
|
||||
{
|
||||
// init fields to 0
|
||||
info->fileName = NULL;
|
||||
info->data = NULL;
|
||||
info->dataSize = 0;
|
||||
info->bitmask = 0;
|
||||
|
||||
// get name
|
||||
if (file_name == NULL) { return 1; }
|
||||
size_t fileNameLen = strlen(file_name);
|
||||
if (fileNameLen == 0) { return 1; }
|
||||
|
||||
info->fileName = (char*)malloc(fileNameLen+1);
|
||||
if (!info->fileName)
|
||||
{
|
||||
// Memory allocation fatal error.
|
||||
return 2;
|
||||
}
|
||||
|
||||
memset(info->fileName, 0, fileNameLen+1);
|
||||
memcpy(info->fileName, file_name, fileNameLen);
|
||||
|
||||
// Load data
|
||||
FILE *fileMiningData = fopen_utf8(info->fileName, "rb");
|
||||
// Failed to open file for reading
|
||||
if (!fileMiningData) { return 1; }
|
||||
|
||||
// Get file size
|
||||
fseek(fileMiningData, 0, SEEK_END);
|
||||
uint64_t fileSize = (uint64_t)ftell(fileMiningData);
|
||||
fseek(fileMiningData, 0, SEEK_SET);
|
||||
|
||||
// Allocate data
|
||||
info->data = (uint8_t *)malloc(fileSize);
|
||||
if (!info->data)
|
||||
{
|
||||
fclose(fileMiningData);
|
||||
// Memory allocation fatal error.
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Load data
|
||||
fread(info->data, fileSize, 1, fileMiningData);
|
||||
fclose(fileMiningData);
|
||||
|
||||
// Update fields
|
||||
info->bitmask = ((fileSize - VH_HASH_OUT_SIZE)/VH_BYTE_ALIGNMENT) + 1;
|
||||
info->dataSize = fileSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void verthash_info_free(verthash_info_t* info)
|
||||
{
|
||||
free(info->fileName);
|
||||
free(info->data);
|
||||
info->dataSize = 0;
|
||||
info->bitmask = 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Verthash hash
|
||||
#define VH_P0_SIZE 64
|
||||
#define VH_N_ITER 8
|
||||
#define VH_N_SUBSET VH_P0_SIZE*VH_N_ITER
|
||||
#define VH_N_ROT 32
|
||||
#define VH_N_INDEXES 4096
|
||||
#define VH_BYTE_ALIGNMENT 16
|
||||
|
||||
static __thread sha3_ctx_t sha3_midstate_ctx;
|
||||
|
||||
void verthash_sha3_prehash_72( const void *data )
|
||||
{
|
||||
sha3_init( &sha3_midstate_ctx, 256 );
|
||||
sha3_update( &sha3_midstate_ctx, data, 72 );
|
||||
}
|
||||
|
||||
void verthash_sha3_final_8( sha3_ctx_t *ctx, void *out, const void *data )
|
||||
{
|
||||
sha3_update( ctx, data, 8 );
|
||||
sha3_final( out, ctx );
|
||||
}
|
||||
|
||||
static inline uint32_t fnv1a(const uint32_t a, const uint32_t b)
|
||||
{
|
||||
return (a ^ b) * 0x1000193;
|
||||
}
|
||||
|
||||
void verthash_hash(const unsigned char* blob_bytes,
|
||||
const size_t blob_size,
|
||||
const unsigned char(*input)[VH_HEADER_SIZE],
|
||||
unsigned char(*output)[VH_HASH_OUT_SIZE])
|
||||
{
|
||||
unsigned char p1[VH_HASH_OUT_SIZE];
|
||||
// sha3_ctx_t sha3_ctx;
|
||||
// memcpy ( &sha3_ctx, &sha3_midstate_ctx, sizeof sha3_ctx );
|
||||
// verthash_sha3_final_8( &sha3_ctx, &p1[0], &input[72] );
|
||||
|
||||
sha3(&input[0], VH_HEADER_SIZE, &p1[0], VH_HASH_OUT_SIZE);
|
||||
|
||||
unsigned char p0[VH_N_SUBSET];
|
||||
|
||||
unsigned char input_header[VH_HEADER_SIZE];
|
||||
memcpy(input_header, input, VH_HEADER_SIZE);
|
||||
|
||||
for (size_t i = 0; i < VH_N_ITER; ++i)
|
||||
{
|
||||
input_header[0] += 1;
|
||||
sha3(&input_header[0], VH_HEADER_SIZE, p0 + i * VH_P0_SIZE, VH_P0_SIZE);
|
||||
}
|
||||
|
||||
uint32_t* p0_index = (uint32_t*)p0;
|
||||
uint32_t seek_indexes[VH_N_INDEXES];
|
||||
|
||||
for (size_t x = 0; x < VH_N_ROT; ++x)
|
||||
{
|
||||
memcpy( seek_indexes + x * (VH_N_SUBSET / sizeof(uint32_t)),
|
||||
p0, VH_N_SUBSET);
|
||||
for (size_t y = 0; y < VH_N_SUBSET / sizeof(uint32_t); ++y)
|
||||
{
|
||||
*(p0_index + y) = ( *(p0_index + y) << 1 )
|
||||
| ( 1 & (*(p0_index + y) >> 31) );
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t* p1_32 = (uint32_t*)p1;
|
||||
uint32_t* blob_bytes_32 = (uint32_t*)blob_bytes;
|
||||
uint32_t value_accumulator = 0x811c9dc5;
|
||||
const uint32_t mdiv = ((blob_size - VH_HASH_OUT_SIZE) / VH_BYTE_ALIGNMENT) + 1;
|
||||
for (size_t i = 0; i < VH_N_INDEXES; i++)
|
||||
{
|
||||
const uint32_t offset = (fnv1a(seek_indexes[i], value_accumulator) % mdiv) * VH_BYTE_ALIGNMENT / sizeof(uint32_t);
|
||||
for (size_t i2 = 0; i2 < VH_HASH_OUT_SIZE / sizeof(uint32_t); i2++)
|
||||
{
|
||||
const uint32_t value = *(blob_bytes_32 + offset + i2);
|
||||
uint32_t* p1_ptr = p1_32 + i2;
|
||||
*p1_ptr = fnv1a(*p1_ptr, value);
|
||||
|
||||
value_accumulator = fnv1a(value_accumulator, value);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(output, p1, VH_HASH_OUT_SIZE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Verthash data file generator
|
||||
|
||||
#define NODE_SIZE 32
|
||||
|
||||
struct Graph
|
||||
{
|
||||
FILE *db;
|
||||
int64_t log2;
|
||||
int64_t pow2;
|
||||
uint8_t *pk;
|
||||
int64_t index;
|
||||
};
|
||||
|
||||
int64_t Log2(int64_t x)
|
||||
{
|
||||
int64_t r = 0;
|
||||
for (; x > 1; x >>= 1)
|
||||
{
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int64_t bfsToPost(struct Graph *g, const int64_t node)
|
||||
{
|
||||
return node & ~g->pow2;
|
||||
}
|
||||
|
||||
int64_t numXi(int64_t index)
|
||||
{
|
||||
return (1 << ((uint64_t)index)) * (index + 1) * index;
|
||||
}
|
||||
|
||||
void WriteId(struct Graph *g, uint8_t *Node, const int64_t id)
|
||||
{
|
||||
fseek(g->db, id * NODE_SIZE, SEEK_SET);
|
||||
fwrite(Node, 1, NODE_SIZE, g->db);
|
||||
}
|
||||
|
||||
void WriteNode(struct Graph *g, uint8_t *Node, const int64_t id)
|
||||
{
|
||||
const int64_t idx = bfsToPost(g, id);
|
||||
WriteId(g, Node, idx);
|
||||
}
|
||||
|
||||
void NewNode(struct Graph *g, const int64_t id, uint8_t *hash)
|
||||
{
|
||||
WriteNode(g, hash, id);
|
||||
}
|
||||
|
||||
uint8_t *GetId(struct Graph *g, const int64_t id)
|
||||
{
|
||||
fseek(g->db, id * NODE_SIZE, SEEK_SET);
|
||||
uint8_t *node = (uint8_t *)malloc(NODE_SIZE);
|
||||
const size_t bytes_read = fread(node, 1, NODE_SIZE, g->db);
|
||||
if(bytes_read != NODE_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
uint8_t *GetNode(struct Graph *g, const int64_t id)
|
||||
{
|
||||
const int64_t idx = bfsToPost(g, id);
|
||||
return GetId(g, idx);
|
||||
}
|
||||
|
||||
uint32_t WriteVarInt(uint8_t *buffer, int64_t val)
|
||||
{
|
||||
memset(buffer, 0, NODE_SIZE);
|
||||
uint64_t uval = ((uint64_t)(val)) << 1;
|
||||
if (val < 0)
|
||||
{
|
||||
uval = ~uval;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
while (uval >= 0x80)
|
||||
{
|
||||
buffer[i] = (uint8_t)uval | 0x80;
|
||||
uval >>= 7;
|
||||
i++;
|
||||
}
|
||||
buffer[i] = (uint8_t)uval;
|
||||
return i;
|
||||
}
|
||||
|
||||
void ButterflyGraph(struct Graph *g, int64_t index, int64_t *count)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
index = 1;
|
||||
}
|
||||
|
||||
int64_t numLevel = 2 * index;
|
||||
int64_t perLevel = (int64_t)(1 << (uint64_t)index);
|
||||
int64_t begin = *count - perLevel;
|
||||
int64_t level, i;
|
||||
|
||||
for (level = 1; level < numLevel; level++)
|
||||
{
|
||||
for (i = 0; i < perLevel; i++)
|
||||
{
|
||||
int64_t prev;
|
||||
int64_t shift = index - level;
|
||||
if (level > numLevel / 2)
|
||||
{
|
||||
shift = level - numLevel / 2;
|
||||
}
|
||||
if (((i >> (uint64_t)shift) & 1) == 0)
|
||||
{
|
||||
prev = i + (1 << (uint64_t)shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = i - (1 << (uint64_t)shift);
|
||||
}
|
||||
|
||||
uint8_t *parent0 = GetNode(g, begin + (level - 1) * perLevel + prev);
|
||||
uint8_t *parent1 = GetNode(g, *count - perLevel);
|
||||
uint8_t *buf = (uint8_t *)malloc(NODE_SIZE);
|
||||
WriteVarInt(buf, *count);
|
||||
uint8_t *hashInput = (uint8_t *)malloc(NODE_SIZE * 4);
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 2), parent0, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 3), parent1, NODE_SIZE);
|
||||
|
||||
uint8_t *hashOutput = (uint8_t *)malloc(NODE_SIZE);
|
||||
sha3(hashInput, NODE_SIZE * 4, hashOutput, NODE_SIZE);
|
||||
|
||||
NewNode(g, *count, hashOutput);
|
||||
(*count)++;
|
||||
|
||||
free(hashOutput);
|
||||
free(hashInput);
|
||||
free(parent0);
|
||||
free(parent1);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XiGraphIter(struct Graph *g, int64_t index)
|
||||
{
|
||||
int64_t count = g->pow2;
|
||||
|
||||
int8_t stackSize = 5;
|
||||
int64_t *stack = (int64_t *)malloc(sizeof(int64_t) * stackSize);
|
||||
for (int i = 0; i < 5; i++)
|
||||
stack[i] = index;
|
||||
|
||||
int8_t graphStackSize = 5;
|
||||
int32_t *graphStack = (int32_t *)malloc(sizeof(int32_t) * graphStackSize);
|
||||
for (int i = 0; i < 5; i++)
|
||||
graphStack[i] = graphStackSize - i - 1;
|
||||
|
||||
int64_t i = 0;
|
||||
int64_t graph = 0;
|
||||
int64_t pow2index = 1 << ((uint64_t)index);
|
||||
|
||||
for (i = 0; i < pow2index; i++)
|
||||
{
|
||||
uint8_t *buf = (uint8_t *)malloc(NODE_SIZE);
|
||||
WriteVarInt(buf, count);
|
||||
uint8_t *hashInput = (uint8_t *)malloc(NODE_SIZE * 2);
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
uint8_t *hashOutput = (uint8_t *)malloc(NODE_SIZE);
|
||||
|
||||
sha3(hashInput, NODE_SIZE * 2, hashOutput, NODE_SIZE);
|
||||
NewNode(g, count, hashOutput);
|
||||
count++;
|
||||
|
||||
free(hashOutput);
|
||||
free(hashInput);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
if (index == 1)
|
||||
{
|
||||
ButterflyGraph(g, index, &count);
|
||||
return;
|
||||
}
|
||||
|
||||
while (stackSize != 0 && graphStackSize != 0)
|
||||
{
|
||||
|
||||
index = stack[stackSize - 1];
|
||||
graph = graphStack[graphStackSize - 1];
|
||||
|
||||
stackSize--;
|
||||
if (stackSize > 0)
|
||||
{
|
||||
int64_t *tempStack = (int64_t *)malloc(sizeof(int64_t) * (stackSize));
|
||||
memcpy(tempStack, stack, sizeof(int64_t) * (stackSize));
|
||||
free(stack);
|
||||
stack = tempStack;
|
||||
}
|
||||
|
||||
graphStackSize--;
|
||||
if (graphStackSize > 0)
|
||||
{
|
||||
int32_t *tempGraphStack = (int32_t *)malloc(sizeof(int32_t) * (graphStackSize));
|
||||
memcpy(tempGraphStack, graphStack, sizeof(int32_t) * (graphStackSize));
|
||||
free(graphStack);
|
||||
graphStack = tempGraphStack;
|
||||
}
|
||||
|
||||
int8_t indicesSize = 5;
|
||||
int64_t *indices = (int64_t *)malloc(sizeof(int64_t) * indicesSize);
|
||||
for (int i = 0; i < indicesSize; i++)
|
||||
indices[i] = index - 1;
|
||||
|
||||
int8_t graphsSize = 5;
|
||||
int32_t *graphs = (int32_t *)malloc(sizeof(int32_t) * graphsSize);
|
||||
for (int i = 0; i < graphsSize; i++)
|
||||
graphs[i] = graphsSize - i - 1;
|
||||
|
||||
int64_t pow2indexInner = 1 << ((uint64_t)index);
|
||||
int64_t pow2indexInner_1 = 1 << ((uint64_t)index - 1);
|
||||
|
||||
if (graph == 0)
|
||||
{
|
||||
uint64_t sources = count - pow2indexInner;
|
||||
for (i = 0; i < pow2indexInner_1; i++)
|
||||
{
|
||||
uint8_t *parent0 = GetNode(g, sources + i);
|
||||
uint8_t *parent1 = GetNode(g, sources + i + pow2indexInner_1);
|
||||
|
||||
uint8_t *buf = (uint8_t *)malloc(NODE_SIZE);
|
||||
WriteVarInt(buf, count);
|
||||
|
||||
uint8_t *hashInput = (uint8_t *)malloc(NODE_SIZE * 4);
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 2), parent0, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 3), parent1, NODE_SIZE);
|
||||
|
||||
uint8_t *hashOutput = (uint8_t *)malloc(NODE_SIZE);
|
||||
sha3(hashInput, NODE_SIZE * 4, hashOutput, NODE_SIZE);
|
||||
|
||||
NewNode(g, count, hashOutput);
|
||||
count++;
|
||||
|
||||
free(hashOutput);
|
||||
free(hashInput);
|
||||
free(parent0);
|
||||
free(parent1);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
else if (graph == 1)
|
||||
{
|
||||
uint64_t firstXi = count;
|
||||
for (i = 0; i < pow2indexInner_1; i++)
|
||||
{
|
||||
uint64_t nodeId = firstXi + i;
|
||||
uint8_t *parent = GetNode(g, firstXi - pow2indexInner_1 + i);
|
||||
|
||||
uint8_t *buf = (uint8_t *)malloc(NODE_SIZE);
|
||||
WriteVarInt(buf, nodeId);
|
||||
|
||||
uint8_t *hashInput = (uint8_t *)malloc(NODE_SIZE * 3);
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 2), parent, NODE_SIZE);
|
||||
|
||||
uint8_t *hashOutput = (uint8_t *)malloc(NODE_SIZE);
|
||||
sha3(hashInput, NODE_SIZE * 3, hashOutput, NODE_SIZE);
|
||||
|
||||
NewNode(g, count, hashOutput);
|
||||
count++;
|
||||
|
||||
free(hashOutput);
|
||||
free(hashInput);
|
||||
free(parent);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
else if (graph == 2)
|
||||
{
|
||||
uint64_t secondXi = count;
|
||||
for (i = 0; i < pow2indexInner_1; i++)
|
||||
{
|
||||
uint64_t nodeId = secondXi + i;
|
||||
uint8_t *parent = GetNode(g, secondXi - pow2indexInner_1 + i);
|
||||
|
||||
uint8_t *buf = (uint8_t *)malloc(NODE_SIZE);
|
||||
WriteVarInt(buf, nodeId);
|
||||
|
||||
uint8_t *hashInput = (uint8_t *)malloc(NODE_SIZE * 3);
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 2), parent, NODE_SIZE);
|
||||
|
||||
uint8_t *hashOutput = (uint8_t *)malloc(NODE_SIZE);
|
||||
sha3(hashInput, NODE_SIZE * 3, hashOutput, NODE_SIZE);
|
||||
|
||||
NewNode(g, count, hashOutput);
|
||||
count++;
|
||||
|
||||
free(hashOutput);
|
||||
free(hashInput);
|
||||
free(parent);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
else if (graph == 3)
|
||||
{
|
||||
uint64_t secondButter = count;
|
||||
for (i = 0; i < pow2indexInner_1; i++)
|
||||
{
|
||||
uint64_t nodeId = secondButter + i;
|
||||
uint8_t *parent = GetNode(g, secondButter - pow2indexInner_1 + i);
|
||||
|
||||
uint8_t *buf = (uint8_t *)malloc(NODE_SIZE);
|
||||
WriteVarInt(buf, nodeId);
|
||||
|
||||
uint8_t *hashInput = (uint8_t *)malloc(NODE_SIZE * 3);
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 2), parent, NODE_SIZE);
|
||||
|
||||
uint8_t *hashOutput = (uint8_t *)malloc(NODE_SIZE);
|
||||
sha3(hashInput, NODE_SIZE * 3, hashOutput, NODE_SIZE);
|
||||
|
||||
NewNode(g, count, hashOutput);
|
||||
count++;
|
||||
|
||||
free(hashOutput);
|
||||
free(hashInput);
|
||||
free(parent);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t sinks = count;
|
||||
uint64_t sources = sinks + pow2indexInner - numXi(index);
|
||||
for (i = 0; i < pow2indexInner_1; i++)
|
||||
{
|
||||
uint64_t nodeId0 = sinks + i;
|
||||
uint64_t nodeId1 = sinks + i + pow2indexInner_1;
|
||||
uint8_t *parent0 = GetNode(g, sinks - pow2indexInner_1 + i);
|
||||
uint8_t *parent1_0 = GetNode(g, sources + i);
|
||||
uint8_t *parent1_1 = GetNode(g, sources + i + pow2indexInner_1);
|
||||
|
||||
uint8_t *buf = (uint8_t *)malloc(NODE_SIZE);
|
||||
WriteVarInt(buf, nodeId0);
|
||||
|
||||
uint8_t *hashInput = (uint8_t *)malloc(NODE_SIZE * 4);
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 2), parent0, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 3), parent1_0, NODE_SIZE);
|
||||
|
||||
uint8_t *hashOutput0 = (uint8_t *)malloc(NODE_SIZE);
|
||||
sha3(hashInput, NODE_SIZE * 4, hashOutput0, NODE_SIZE);
|
||||
|
||||
WriteVarInt(buf, nodeId1);
|
||||
|
||||
memcpy(hashInput, g->pk, NODE_SIZE);
|
||||
memcpy(hashInput + NODE_SIZE, buf, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 2), parent0, NODE_SIZE);
|
||||
memcpy(hashInput + (NODE_SIZE * 3), parent1_1, NODE_SIZE);
|
||||
|
||||
uint8_t *hashOutput1 = (uint8_t *)malloc(NODE_SIZE);
|
||||
sha3(hashInput, NODE_SIZE * 4, hashOutput1, NODE_SIZE);
|
||||
|
||||
NewNode(g, nodeId0, hashOutput0);
|
||||
NewNode(g, nodeId1, hashOutput1);
|
||||
count += 2;
|
||||
|
||||
free(parent0);
|
||||
free(parent1_0);
|
||||
free(parent1_1);
|
||||
free(buf);
|
||||
free(hashInput);
|
||||
free(hashOutput0);
|
||||
free(hashOutput1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((graph == 0 || graph == 3) ||
|
||||
((graph == 1 || graph == 2) && index == 2))
|
||||
{
|
||||
ButterflyGraph(g, index - 1, &count);
|
||||
}
|
||||
else if (graph == 1 || graph == 2)
|
||||
{
|
||||
|
||||
int64_t *tempStack = (int64_t *)malloc(sizeof(int64_t) * (stackSize + indicesSize));
|
||||
memcpy(tempStack, stack, stackSize * sizeof(int64_t));
|
||||
memcpy(tempStack + stackSize, indices, indicesSize * sizeof(int64_t));
|
||||
stackSize += indicesSize;
|
||||
free(stack);
|
||||
stack = tempStack;
|
||||
|
||||
int32_t *tempGraphStack = (int32_t *)malloc(sizeof(int32_t) * (graphStackSize + graphsSize));
|
||||
memcpy(tempGraphStack, graphStack, graphStackSize * sizeof(int32_t));
|
||||
memcpy(tempGraphStack + graphStackSize, graphs, graphsSize * sizeof(int32_t));
|
||||
graphStackSize += graphsSize;
|
||||
free(graphStack);
|
||||
graphStack = tempGraphStack;
|
||||
}
|
||||
|
||||
free(indices);
|
||||
free(graphs);
|
||||
}
|
||||
|
||||
free(stack);
|
||||
free(graphStack);
|
||||
}
|
||||
|
||||
struct Graph *NewGraph(int64_t index, const char* targetFile, uint8_t *pk)
|
||||
{
|
||||
uint8_t exists = 0;
|
||||
FILE *db;
|
||||
if ((db = fopen_utf8(targetFile, "r")) != NULL)
|
||||
{
|
||||
fclose(db);
|
||||
exists = 1;
|
||||
}
|
||||
|
||||
db = fopen_utf8(targetFile, "wb+");
|
||||
int64_t size = numXi(index);
|
||||
int64_t log2 = Log2(size) + 1;
|
||||
int64_t pow2 = 1 << ((uint64_t)log2);
|
||||
|
||||
struct Graph *g = (struct Graph *)malloc(sizeof(struct Graph));
|
||||
g->db = db;
|
||||
g->log2 = log2;
|
||||
g->pow2 = pow2;
|
||||
g->pk = pk;
|
||||
g->index = index;
|
||||
|
||||
if (exists == 0)
|
||||
{
|
||||
XiGraphIter(g, index);
|
||||
}
|
||||
|
||||
fclose(db);
|
||||
return g;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int verthash_generate_data_file(const char* output_file_name)
|
||||
{
|
||||
const char *hashInput = "Verthash Proof-of-Space Datafile";
|
||||
uint8_t *pk = (uint8_t*)malloc(NODE_SIZE);
|
||||
sha3(hashInput, 32, pk, NODE_SIZE);
|
||||
|
||||
int64_t index = 17;
|
||||
NewGraph(index, output_file_name, pk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
61
algo/verthash/Verthash.h
Normal file
61
algo/verthash/Verthash.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2018-2021 CryptoGraphics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version. See LICENSE for more details.
|
||||
*/
|
||||
|
||||
#ifndef Verthash_INCLUDE_ONCE
|
||||
#define Verthash_INCLUDE_ONCE
|
||||
|
||||
#include "tiny_sha3/sha3.h"
|
||||
#include "fopen_utf8.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// Verthash constants used to compute bitmask, used inside kernel during IO pass
|
||||
#define VH_HASH_OUT_SIZE 32
|
||||
#define VH_BYTE_ALIGNMENT 16
|
||||
#define VH_HEADER_SIZE 80
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Verthash data
|
||||
//! Verthash C api for data maniputation.
|
||||
typedef struct VerthashInfo
|
||||
{
|
||||
char* fileName;
|
||||
uint8_t* data;
|
||||
uint64_t dataSize;
|
||||
uint32_t bitmask;
|
||||
} verthash_info_t;
|
||||
|
||||
//! Must be called before usage. Reset all fields and set a mining data file name.
|
||||
//! Error codes
|
||||
//! 0 - Success(No error).
|
||||
//! 1 - File name is invalid.
|
||||
//! 2 - Memory allocation error
|
||||
int verthash_info_init(verthash_info_t* info, const char* file_name);
|
||||
|
||||
//! Reset all fields and free allocated data.
|
||||
void verthash_info_free(verthash_info_t* info);
|
||||
|
||||
//! Generate verthash data file and save it to specified location.
|
||||
int verthash_generate_data_file(const char* output_file_name);
|
||||
|
||||
void verthash_sha3_prehash_72( const void *data );
|
||||
|
||||
void verthash_sha3_final_8( sha3_ctx_t *ctx, void *out, const void *data );
|
||||
|
||||
void verthash_hash(const unsigned char* blob_bytes,
|
||||
const size_t blob_size,
|
||||
const unsigned char(*input)[VH_HEADER_SIZE],
|
||||
unsigned char(*output)[VH_HASH_OUT_SIZE]);
|
||||
|
||||
|
||||
#endif // !Verthash_INCLUDE_ONCE
|
||||
|
181
algo/verthash/fopen_utf8.c
Normal file
181
algo/verthash/fopen_utf8.c
Normal file
@@ -0,0 +1,181 @@
|
||||
#ifndef H_FOPEN_UTF8
|
||||
#define H_FOPEN_UTF8
|
||||
|
||||
#include "fopen_utf8.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int utf8_char_size(const uint8_t *c)
|
||||
{
|
||||
const uint8_t m0x = 0x80, c0x = 0x00,
|
||||
m10x = 0xC0, c10x = 0x80,
|
||||
m110x = 0xE0, c110x = 0xC0,
|
||||
m1110x = 0xF0, c1110x = 0xE0,
|
||||
m11110x = 0xF8, c11110x = 0xF0;
|
||||
|
||||
if ((c[0] & m0x) == c0x)
|
||||
return 1;
|
||||
|
||||
if ((c[0] & m110x) == c110x)
|
||||
if ((c[1] & m10x) == c10x)
|
||||
return 2;
|
||||
|
||||
if ((c[0] & m1110x) == c1110x)
|
||||
if ((c[1] & m10x) == c10x)
|
||||
if ((c[2] & m10x) == c10x)
|
||||
return 3;
|
||||
|
||||
if ((c[0] & m11110x) == c11110x)
|
||||
if ((c[1] & m10x) == c10x)
|
||||
if ((c[2] & m10x) == c10x)
|
||||
if ((c[3] & m10x) == c10x)
|
||||
return 4;
|
||||
|
||||
if ((c[0] & m10x) == c10x) // not a first UTF-8 byte
|
||||
return 0;
|
||||
|
||||
return -1; // if c[0] is a first byte but the other bytes don't match
|
||||
}
|
||||
|
||||
uint32_t utf8_to_unicode32(const uint8_t *c, size_t *index)
|
||||
{
|
||||
uint32_t v;
|
||||
int size;
|
||||
const uint8_t m6 = 63, m5 = 31, m4 = 15, m3 = 7;
|
||||
|
||||
if (c==NULL)
|
||||
return 0;
|
||||
|
||||
size = utf8_char_size(c);
|
||||
|
||||
if (size > 0 && index)
|
||||
*index += size-1;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
v = c[0];
|
||||
break;
|
||||
case 2:
|
||||
v = c[0] & m5;
|
||||
v = v << 6 | (c[1] & m6);
|
||||
break;
|
||||
case 3:
|
||||
v = c[0] & m4;
|
||||
v = v << 6 | (c[1] & m6);
|
||||
v = v << 6 | (c[2] & m6);
|
||||
break;
|
||||
case 4:
|
||||
v = c[0] & m3;
|
||||
v = v << 6 | (c[1] & m6);
|
||||
v = v << 6 | (c[2] & m6);
|
||||
v = v << 6 | (c[3] & m6);
|
||||
break;
|
||||
case 0: // not a first UTF-8 byte
|
||||
case -1: // corrupt UTF-8 letter
|
||||
default:
|
||||
v = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int codepoint_utf16_size(uint32_t c)
|
||||
{
|
||||
if (c < 0x10000) return 1;
|
||||
if (c < 0x110000) return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t *sprint_utf16(uint16_t *str, uint32_t c) // str must be able to hold 1 to 3 entries and will be null-terminated by this function
|
||||
{
|
||||
int c_size;
|
||||
|
||||
if (str==NULL)
|
||||
return NULL;
|
||||
|
||||
c_size = codepoint_utf16_size(c);
|
||||
|
||||
switch (c_size)
|
||||
{
|
||||
case 1:
|
||||
str[0] = c;
|
||||
if (c > 0)
|
||||
str[1] = '\0';
|
||||
break;
|
||||
|
||||
case 2:
|
||||
c -= 0x10000;
|
||||
str[0] = 0xD800 + (c >> 10);
|
||||
str[1] = 0xDC00 + (c & 0x3FF);
|
||||
str[2] = '\0';
|
||||
break;
|
||||
|
||||
default:
|
||||
str[0] = '\0';
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
size_t strlen_utf8_to_utf16(const uint8_t *str)
|
||||
{
|
||||
size_t i, count;
|
||||
uint32_t c;
|
||||
|
||||
for (i=0, count=0; ; i++)
|
||||
{
|
||||
if (str[i]==0)
|
||||
return count;
|
||||
|
||||
c = utf8_to_unicode32(&str[i], &i);
|
||||
count += codepoint_utf16_size(c);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t *utf8_to_utf16(const uint8_t *utf8, uint16_t *utf16)
|
||||
{
|
||||
size_t i, j;
|
||||
uint32_t c;
|
||||
|
||||
if (utf8==NULL)
|
||||
return NULL;
|
||||
|
||||
if (utf16==NULL)
|
||||
utf16 = (uint16_t *) calloc(strlen_utf8_to_utf16(utf8) + 1, sizeof(uint16_t));
|
||||
|
||||
for (i=0, j=0, c=1; c; i++)
|
||||
{
|
||||
c = utf8_to_unicode32(&utf8[i], &i);
|
||||
sprint_utf16(&utf16[j], c);
|
||||
j += codepoint_utf16_size(c);
|
||||
}
|
||||
|
||||
return utf16;
|
||||
}
|
||||
|
||||
FILE *fopen_utf8(const char *path, const char *mode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wchar_t *wpath, wmode[8];
|
||||
FILE *file;
|
||||
|
||||
if (utf8_to_utf16((const uint8_t *) mode, (uint16_t *) wmode)==NULL)
|
||||
return NULL;
|
||||
|
||||
wpath = (wchar_t *) utf8_to_utf16((const uint8_t *) path, NULL);
|
||||
if (wpath==NULL)
|
||||
return NULL;
|
||||
|
||||
file = _wfopen(wpath, wmode);
|
||||
free(wpath);
|
||||
return file;
|
||||
#else
|
||||
return fopen(path, mode);
|
||||
#endif
|
||||
}
|
||||
#endif
|
25
algo/verthash/fopen_utf8.h
Normal file
25
algo/verthash/fopen_utf8.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef H_FOPEN_UTF8
|
||||
#define H_FOPEN_UTF8
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int utf8_char_size(const uint8_t *c);
|
||||
uint32_t utf8_to_unicode32(const uint8_t *c, size_t *index);
|
||||
int codepoint_utf16_size(uint32_t c);
|
||||
uint16_t *sprint_utf16(uint16_t *str, uint32_t c);
|
||||
size_t strlen_utf8_to_utf16(const uint8_t *str);
|
||||
uint16_t *utf8_to_utf16(const uint8_t *utf8, uint16_t *utf16);
|
||||
|
||||
FILE *fopen_utf8(const char *path, const char *mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
191
algo/verthash/tiny_sha3/sha3.c
Normal file
191
algo/verthash/tiny_sha3/sha3.c
Normal file
@@ -0,0 +1,191 @@
|
||||
// sha3.c
|
||||
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||
|
||||
// Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3"
|
||||
// Revised 03-Sep-15 for portability + OpenSSL - style API
|
||||
|
||||
#include "sha3.h"
|
||||
|
||||
// update the state with given number of rounds
|
||||
|
||||
void sha3_keccakf(uint64_t st[25])
|
||||
{
|
||||
// constants
|
||||
const uint64_t keccakf_rndc[24] = {
|
||||
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
|
||||
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
|
||||
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
|
||||
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
||||
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
|
||||
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
|
||||
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
|
||||
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
|
||||
};
|
||||
const int keccakf_rotc[24] = {
|
||||
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
|
||||
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
|
||||
};
|
||||
const int keccakf_piln[24] = {
|
||||
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
|
||||
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
|
||||
};
|
||||
|
||||
// variables
|
||||
int i, j, r;
|
||||
uint64_t t, bc[5];
|
||||
|
||||
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
||||
uint8_t *v;
|
||||
|
||||
// endianess conversion. this is redundant on little-endian targets
|
||||
for (i = 0; i < 25; i++) {
|
||||
v = (uint8_t *) &st[i];
|
||||
st[i] = ((uint64_t) v[0]) | (((uint64_t) v[1]) << 8) |
|
||||
(((uint64_t) v[2]) << 16) | (((uint64_t) v[3]) << 24) |
|
||||
(((uint64_t) v[4]) << 32) | (((uint64_t) v[5]) << 40) |
|
||||
(((uint64_t) v[6]) << 48) | (((uint64_t) v[7]) << 56);
|
||||
}
|
||||
#endif
|
||||
|
||||
// actual iteration
|
||||
for (r = 0; r < KECCAKF_ROUNDS; r++) {
|
||||
|
||||
// Theta
|
||||
for (i = 0; i < 5; i++)
|
||||
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
|
||||
for (j = 0; j < 25; j += 5)
|
||||
st[j + i] ^= t;
|
||||
}
|
||||
|
||||
// Rho Pi
|
||||
t = st[1];
|
||||
for (i = 0; i < 24; i++) {
|
||||
j = keccakf_piln[i];
|
||||
bc[0] = st[j];
|
||||
st[j] = ROTL64(t, keccakf_rotc[i]);
|
||||
t = bc[0];
|
||||
}
|
||||
|
||||
// Chi
|
||||
for (j = 0; j < 25; j += 5) {
|
||||
for (i = 0; i < 5; i++)
|
||||
bc[i] = st[j + i];
|
||||
for (i = 0; i < 5; i++)
|
||||
st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
|
||||
}
|
||||
|
||||
// Iota
|
||||
st[0] ^= keccakf_rndc[r];
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
||||
// endianess conversion. this is redundant on little-endian targets
|
||||
for (i = 0; i < 25; i++) {
|
||||
v = (uint8_t *) &st[i];
|
||||
t = st[i];
|
||||
v[0] = t & 0xFF;
|
||||
v[1] = (t >> 8) & 0xFF;
|
||||
v[2] = (t >> 16) & 0xFF;
|
||||
v[3] = (t >> 24) & 0xFF;
|
||||
v[4] = (t >> 32) & 0xFF;
|
||||
v[5] = (t >> 40) & 0xFF;
|
||||
v[6] = (t >> 48) & 0xFF;
|
||||
v[7] = (t >> 56) & 0xFF;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Initialize the context for SHA3
|
||||
|
||||
int sha3_init(sha3_ctx_t *c, int mdlen)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 25; i++)
|
||||
c->st.q[i] = 0;
|
||||
c->mdlen = mdlen;
|
||||
c->rsiz = 200 - 2 * mdlen;
|
||||
c->pt = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// update state with more data
|
||||
|
||||
int sha3_update(sha3_ctx_t *c, const void *data, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
int j;
|
||||
|
||||
j = c->pt;
|
||||
for (i = 0; i < len; i++) {
|
||||
c->st.b[j++] ^= ((const uint8_t *) data)[i];
|
||||
if (j >= c->rsiz) {
|
||||
sha3_keccakf(c->st.q);
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
c->pt = j;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// finalize and output a hash
|
||||
|
||||
int sha3_final(void *md, sha3_ctx_t *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
c->st.b[c->pt] ^= 0x06;
|
||||
c->st.b[c->rsiz - 1] ^= 0x80;
|
||||
sha3_keccakf(c->st.q);
|
||||
|
||||
for (i = 0; i < c->mdlen; i++) {
|
||||
((uint8_t *) md)[i] = c->st.b[i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compute a SHA-3 hash (md) of given byte length from "in"
|
||||
|
||||
void *sha3(const void *in, size_t inlen, void *md, int mdlen)
|
||||
{
|
||||
sha3_ctx_t sha3;
|
||||
|
||||
sha3_init(&sha3, mdlen);
|
||||
sha3_update(&sha3, in, inlen);
|
||||
sha3_final(md, &sha3);
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
// SHAKE128 and SHAKE256 extensible-output functionality
|
||||
|
||||
void shake_xof(sha3_ctx_t *c)
|
||||
{
|
||||
c->st.b[c->pt] ^= 0x1F;
|
||||
c->st.b[c->rsiz - 1] ^= 0x80;
|
||||
sha3_keccakf(c->st.q);
|
||||
c->pt = 0;
|
||||
}
|
||||
|
||||
void shake_out(sha3_ctx_t *c, void *out, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
int j;
|
||||
|
||||
j = c->pt;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (j >= c->rsiz) {
|
||||
sha3_keccakf(c->st.q);
|
||||
j = 0;
|
||||
}
|
||||
((uint8_t *) out)[i] = c->st.b[j++];
|
||||
}
|
||||
c->pt = j;
|
||||
}
|
||||
|
55
algo/verthash/tiny_sha3/sha3.h
Normal file
55
algo/verthash/tiny_sha3/sha3.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// sha3.h
|
||||
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||
|
||||
#ifndef SHA3_H
|
||||
#define SHA3_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef KECCAKF_ROUNDS
|
||||
#define KECCAKF_ROUNDS 24
|
||||
#endif
|
||||
|
||||
#ifndef ROTL64
|
||||
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
|
||||
#endif
|
||||
|
||||
// state context
|
||||
typedef struct {
|
||||
union { // state:
|
||||
uint8_t b[200]; // 8-bit bytes
|
||||
uint64_t q[25]; // 64-bit words
|
||||
} st;
|
||||
int pt, rsiz, mdlen; // these don't overflow
|
||||
} sha3_ctx_t;
|
||||
|
||||
// Compression function.
|
||||
void sha3_keccakf(uint64_t st[25]);
|
||||
|
||||
// OpenSSL - like interfece
|
||||
int sha3_init(sha3_ctx_t *c, int mdlen); // mdlen = hash output in bytes
|
||||
int sha3_update(sha3_ctx_t *c, const void *data, size_t len);
|
||||
int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md
|
||||
|
||||
// compute a sha3 hash (md) of given byte length from "in"
|
||||
void *sha3(const void *in, size_t inlen, void *md, int mdlen);
|
||||
|
||||
// SHAKE128 and SHAKE256 extensible-output functions
|
||||
#define shake128_init(c) sha3_init(c, 16)
|
||||
#define shake256_init(c) sha3_init(c, 32)
|
||||
#define shake_update sha3_update
|
||||
|
||||
void shake_xof(sha3_ctx_t *c);
|
||||
void shake_out(sha3_ctx_t *c, void *out, size_t len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
96
algo/verthash/verthash-gate.c
Normal file
96
algo/verthash/verthash-gate.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "algo-gate-api.h"
|
||||
#include "algo/sha/sph_sha2.h"
|
||||
#include "Verthash.h"
|
||||
|
||||
static verthash_info_t verthashInfo;
|
||||
|
||||
// Verthash data file hash in bytes for verification
|
||||
// 0x48aa21d7afededb63976d48a8ff8ec29d5b02563af4a1110b056cd43e83155a5
|
||||
static const uint8_t verthashDatFileHash_bytes[32] =
|
||||
{ 0xa5, 0x55, 0x31, 0xe8, 0x43, 0xcd, 0x56, 0xb0,
|
||||
0x10, 0x11, 0x4a, 0xaf, 0x63, 0x25, 0xb0, 0xd5,
|
||||
0x29, 0xec, 0xf8, 0x8f, 0x8a, 0xd4, 0x76, 0x39,
|
||||
0xb6, 0xed, 0xed, 0xaf, 0xd7, 0x21, 0xaa, 0x48 };
|
||||
|
||||
static const char* verthash_data_file_name = "verthash.dat";
|
||||
|
||||
int scanhash_verthash( struct work *work, uint32_t max_nonce,
|
||||
uint64_t *hashes_done, struct thr_info *mythr )
|
||||
{
|
||||
uint32_t edata[20] __attribute__((aligned(64)));
|
||||
uint32_t hash[8] __attribute__((aligned(64)));
|
||||
uint32_t *pdata = work->data;
|
||||
uint32_t *ptarget = work->target;
|
||||
const uint32_t first_nonce = pdata[19];
|
||||
const uint32_t last_nonce = max_nonce - 1;
|
||||
uint32_t n = first_nonce;
|
||||
const int thr_id = mythr->id;
|
||||
const bool bench = opt_benchmark;
|
||||
|
||||
mm128_bswap32_80( edata, pdata );
|
||||
// verthash_sha3_prehash_72( edata );
|
||||
do
|
||||
{
|
||||
edata[19] = n;
|
||||
verthash_hash( verthashInfo.data, verthashInfo.dataSize,
|
||||
(const unsigned char (*)[80]) edata,
|
||||
(unsigned char (*)[32]) hash );
|
||||
if ( valid_hash( hash, ptarget ) && !bench )
|
||||
{
|
||||
pdata[19] = bswap_32( n );
|
||||
submit_solution( work, hash, mythr );
|
||||
}
|
||||
n++;
|
||||
} while ( n < last_nonce && !work_restart[thr_id].restart );
|
||||
*hashes_done = n - first_nonce;
|
||||
pdata[19] = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool register_verthash_algo( algo_gate_t* gate )
|
||||
{
|
||||
|
||||
opt_target_factor = 256.0;
|
||||
gate->scanhash = (void*)&scanhash_verthash;
|
||||
|
||||
// verthash data file
|
||||
int vhLoadResult = verthash_info_init(&verthashInfo, verthash_data_file_name );
|
||||
// Check Verthash initialization status
|
||||
if (vhLoadResult == 0) // No Error
|
||||
{
|
||||
applog(LOG_INFO, "Verthash data file has been loaded succesfully!");
|
||||
|
||||
// and verify data file(if it was enabled)
|
||||
if ( true )
|
||||
// if (!cmdr.disableVerthashDataFileVerification)
|
||||
{
|
||||
uint8_t vhDataFileHash[32] = { 0 };
|
||||
sph_sha256_full( vhDataFileHash, verthashInfo.data,
|
||||
verthashInfo.dataSize );
|
||||
|
||||
if ( memcmp( vhDataFileHash, verthashDatFileHash_bytes,
|
||||
sizeof(verthashDatFileHash_bytes) ) == 0 )
|
||||
applog(LOG_INFO, "Verthash data file has been verified succesfully!");
|
||||
else
|
||||
applog(LOG_ERR, "Verthash data file verification has failed!");
|
||||
}
|
||||
else
|
||||
applog(LOG_WARNING, "Verthash data file verification stage is disabled!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle Verthash error codes
|
||||
if (vhLoadResult == 1)
|
||||
applog(LOG_ERR, "Verthash data file name is invalid");
|
||||
else if (vhLoadResult == 2)
|
||||
applog(LOG_ERR, "Failed to allocate memory for Verthash data");
|
||||
else // for debugging purposes
|
||||
applog(LOG_ERR, "Verthash data initialization unknown error code: %d",
|
||||
vhLoadResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
20
configure
vendored
20
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.15.7.
|
||||
# Generated by GNU Autoconf 2.69 for cpuminer-opt 3.15.8.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -577,8 +577,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='cpuminer-opt'
|
||||
PACKAGE_TARNAME='cpuminer-opt'
|
||||
PACKAGE_VERSION='3.15.7'
|
||||
PACKAGE_STRING='cpuminer-opt 3.15.7'
|
||||
PACKAGE_VERSION='3.15.8'
|
||||
PACKAGE_STRING='cpuminer-opt 3.15.8'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1332,7 +1332,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures cpuminer-opt 3.15.7 to adapt to many kinds of systems.
|
||||
\`configure' configures cpuminer-opt 3.15.8 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1404,7 +1404,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of cpuminer-opt 3.15.7:";;
|
||||
short | recursive ) echo "Configuration of cpuminer-opt 3.15.8:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1509,7 +1509,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
cpuminer-opt configure 3.15.7
|
||||
cpuminer-opt configure 3.15.8
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2012,7 +2012,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by cpuminer-opt $as_me 3.15.7, which was
|
||||
It was created by cpuminer-opt $as_me 3.15.8, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2993,7 +2993,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='cpuminer-opt'
|
||||
VERSION='3.15.7'
|
||||
VERSION='3.15.8'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@@ -6690,7 +6690,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by cpuminer-opt $as_me 3.15.7, which was
|
||||
This file was extended by cpuminer-opt $as_me 3.15.8, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -6756,7 +6756,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
cpuminer-opt config.status 3.15.7
|
||||
cpuminer-opt config.status 3.15.8
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
AC_INIT([cpuminer-opt], [3.15.7])
|
||||
AC_INIT([cpuminer-opt], [3.16.0])
|
||||
|
||||
AC_PREREQ([2.59c])
|
||||
AC_CANONICAL_SYSTEM
|
||||
|
12
cpu-miner.c
12
cpu-miner.c
@@ -119,14 +119,14 @@ bool opt_sapling = false;
|
||||
// Need compile time and run time test.
|
||||
#if defined(__linux) && defined(GCC_INT128)
|
||||
#define AFFINITY_USES_UINT128 1
|
||||
uint128_t opt_affinity = -1;
|
||||
static uint128_t opt_affinity = -1;
|
||||
static bool affinity_uses_uint128 = true;
|
||||
#else
|
||||
uint64_t opt_affinity = -1;
|
||||
static uint64_t opt_affinity = -1;
|
||||
static bool affinity_uses_uint128 = false;
|
||||
#endif
|
||||
|
||||
int opt_priority = 0;
|
||||
int opt_priority = 0; // deprecated
|
||||
int num_cpus = 1;
|
||||
int num_cpugroups = 1;
|
||||
char *rpc_url = NULL;;
|
||||
@@ -3186,14 +3186,12 @@ void parse_arg(int key, char *arg )
|
||||
ul = strtoull( p, NULL, 16 );
|
||||
else
|
||||
ul = atoll( arg );
|
||||
// if ( ul > ( 1ULL << num_cpus ) - 1ULL )
|
||||
// ul = -1LL;
|
||||
#if AFFINITY_USES_UINT128
|
||||
// replicate the low 64 bits to make a full 128 bit mask if there are more
|
||||
// than 64 CPUs, otherwise zero extend the upper half.
|
||||
opt_affinity = (uint128_t)ul;
|
||||
if ( num_cpus > 64 )
|
||||
opt_affinity = (opt_affinity << 64 ) | opt_affinity;
|
||||
opt_affinity |= opt_affinity << 64;
|
||||
#else
|
||||
opt_affinity = ul;
|
||||
#endif
|
||||
@@ -3202,6 +3200,8 @@ void parse_arg(int key, char *arg )
|
||||
v = atoi(arg);
|
||||
if (v < 0 || v > 5) /* sanity check */
|
||||
show_usage_and_exit(1);
|
||||
// option is deprecated, show warning
|
||||
applog( LOG_WARNING, "High priority mining threads may cause system instability");
|
||||
opt_priority = v;
|
||||
break;
|
||||
case 'N': // N parameter for various scrypt algos
|
||||
|
3
miner.h
3
miner.h
@@ -573,6 +573,7 @@ enum algos {
|
||||
ALGO_TRIBUS,
|
||||
ALGO_VANILLA,
|
||||
ALGO_VELTOR,
|
||||
ALGO_VERTHASH,
|
||||
ALGO_WHIRLPOOL,
|
||||
ALGO_WHIRLPOOLX,
|
||||
ALGO_X11,
|
||||
@@ -665,6 +666,7 @@ static const char* const algo_names[] = {
|
||||
"tribus",
|
||||
"vanilla",
|
||||
"veltor",
|
||||
"verthash",
|
||||
"whirlpool",
|
||||
"whirlpoolx",
|
||||
"x11",
|
||||
@@ -824,6 +826,7 @@ Options:\n\
|
||||
tribus Denarius (DNR)\n\
|
||||
vanilla blake256r8vnl (VCash)\n\
|
||||
veltor\n\
|
||||
verthash\n\
|
||||
whirlpool\n\
|
||||
whirlpoolx\n\
|
||||
x11 Dash\n\
|
||||
|
17
verthash-help.txt
Normal file
17
verthash-help.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
The verthash data file must be named verthash.dat and located in the same
|
||||
directory as the cpuminer executable. A Linux symlink works.
|
||||
|
||||
The verthash data file must be obtained seperately. If you already use
|
||||
VerthashMiner you can simply copy or link the existing data file to the
|
||||
cpuminer directory, using the required name.
|
||||
|
||||
Otherwise it may be created using
|
||||
https://github.com/CryptoGraphics/VerthashMiner/releases
|
||||
following the instructions. A GPU is not necessary to create the file.
|
||||
|
||||
The same data file can be used by both cpuminer and VerthashMiner
|
||||
simultaneously.
|
||||
|
||||
Launching cpuminer to mine verthash is the same as any other algorithm,
|
||||
no extra options are required.
|
@@ -31,6 +31,7 @@ mkdir release
|
||||
cp README.txt release/
|
||||
cp README.md release/
|
||||
cp RELEASE_NOTES release/
|
||||
cp verthash-help.txt release/
|
||||
cp $MINGW_LIB/zlib1.dll release/
|
||||
cp $MINGW_LIB/libwinpthread-1.dll release/
|
||||
cp $GCC_MINGW_LIB/libstdc++-6.dll release/
|
||||
|
Reference in New Issue
Block a user