GOSTcoin support for ccminer CUDA miner project, compatible with most nvidia cards
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.9 KiB

/*
* Port to Generic C of C++ implementation of the Equihash Proof-of-Work
* algorithm from zcashd.
*
* Copyright (c) 2016 abc at openwall dot com
* Copyright (c) 2016 Jack Grigg
* Copyright (c) 2016 The Zcash developers
* Copyright (c) 2017 tpruvot
*
* Distributed under the MIT software license, see the accompanying
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
*/
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "equihash.h"
//#define USE_LIBSODIUM
#ifdef USE_LIBSODIUM
#include "sodium.h"
#define blake2b_state crypto_generichash_blake2b_state
#else
#include "blake2/blake2.h"
#define be32toh(x) swab32(x)
#define htole32(x) (x)
#define HASHOUT 50
#endif
#include <miner.h>
static void digestInit(blake2b_state *S, const uint32_t n, const uint32_t k)
{
uint32_t le_N = htole32(n);
uint32_t le_K = htole32(k);
#ifdef USE_LIBSODIUM
uint8_t personalization[crypto_generichash_blake2b_PERSONALBYTES] = { 0 };
memcpy(personalization, "ZcashPoW", 8);
memcpy(personalization + 8, &le_N, 4);
memcpy(personalization + 12, &le_K, 4);
crypto_generichash_blake2b_init_salt_personal(S,
NULL, 0, (512 / n) * n / 8, NULL, personalization);
#else
unsigned char personal[] = "ZcashPoW01230123";
memcpy(personal + 8, &le_N, 4);
memcpy(personal + 12, &le_K, 4);
blake2b_param P[1];
P->digest_length = HASHOUT;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
P->leaf_length = 0;
P->node_offset = 0;
P->node_depth = 0;
P->inner_length = 0;
memset(P->reserved, 0, sizeof(P->reserved));
memset(P->salt, 0, sizeof(P->salt));
memcpy(P->personal, (const uint8_t *)personal, 16);
eq_blake2b_init_param(S, P);
#endif
}
static void expandArray(const unsigned char *in, const uint32_t in_len,
unsigned char *out, const uint32_t out_len,
const uint32_t bit_len, const uint32_t byte_pad)
{
assert(bit_len >= 8);
assert(8 * sizeof(uint32_t) >= 7 + bit_len);
const uint32_t out_width = (bit_len + 7) / 8 + byte_pad;
assert(out_len == 8 * out_width * in_len / bit_len);
const uint32_t bit_len_mask = ((uint32_t)1 << bit_len) - 1;
// The acc_bits least-significant bits of acc_value represent a bit sequence
// in big-endian order.
uint32_t acc_bits = 0;
uint32_t acc_value = 0;
uint32_t j = 0;
for (uint32_t i = 0; i < in_len; i++)
{
acc_value = (acc_value << 8) | in[i];
acc_bits += 8;
// When we have bit_len or more bits in the accumulator, write the next
// output element.
if (acc_bits >= bit_len) {
acc_bits -= bit_len;
for (uint32_t x = 0; x < byte_pad; x++) {
out[j + x] = 0;
}
for (uint32_t x = byte_pad; x < out_width; x++) {
out[j + x] = (
// Big-endian
acc_value >> (acc_bits + (8 * (out_width - x - 1)))
) & (
// Apply bit_len_mask across byte boundaries
(bit_len_mask >> (8 * (out_width - x - 1))) & 0xFF
);
}
j += out_width;
}
}
}
static void generateHash(blake2b_state *S, const uint32_t g, uint8_t *hash, const size_t hashLen)
{
const uint32_t le_g = htole32(g);
blake2b_state digest = *S; /* copy */
#ifdef USE_LIBSODIUM
crypto_generichash_blake2b_update(&digest, (uint8_t *)&le_g, sizeof(le_g));
crypto_generichash_blake2b_final(&digest, hash, hashLen);
#else
eq_blake2b_update(&digest, (const uint8_t*) &le_g, sizeof(le_g));
eq_blake2b_final(&digest, hash, (uint8_t) (hashLen & 0xFF));
#endif
}
static int isZero(const uint8_t *hash, size_t len)
{
// This doesn't need to be constant time.
for (size_t i = 0; i < len; i++) {
if (hash[i] != 0) return 0;
}
return 1;
}
// hdr -> header including nonce (140 bytes)
// soln -> equihash solution (excluding 3 bytes with size, so 1344 bytes length)
bool equi_verify(uint8_t* const hdr, uint8_t* const soln)
{
const uint32_t n = WN; // 200
const uint32_t k = WK; // 9
const uint32_t collisionBitLength = n / (k + 1);
const uint32_t collisionByteLength = (collisionBitLength + 7) / 8;
const uint32_t hashLength = (k + 1) * collisionByteLength;
const uint32_t indicesPerHashOutput = 512 / n;
const uint32_t hashOutput = indicesPerHashOutput * n / 8;
const uint32_t equihashSolutionSize = (1 << k) * (n / (k + 1) + 1) / 8;
const uint32_t solnr = 1 << k;
uint32_t indices[512] = { 0 };
uint8_t vHash[hashLength] = { 0 };
blake2b_state state;
digestInit(&state, n, k);
#ifdef USE_LIBSODIUM
crypto_generichash_blake2b_update(&state, hdr, 140);
#else
eq_blake2b_update(&state, hdr, 140);
#endif
expandArray(soln, equihashSolutionSize, (uint8_t*) &indices, sizeof(indices), collisionBitLength + 1, 1);
for (uint32_t j = 0; j < solnr; j++) {
uint8_t tmpHash[hashOutput];
uint8_t hash[hashLength];
uint32_t i = be32toh(indices[j]);
generateHash(&state, i / indicesPerHashOutput, tmpHash, hashOutput);
expandArray(tmpHash + (i % indicesPerHashOutput * n / 8), n / 8, hash, hashLength, collisionBitLength, 0);
for (uint32_t k = 0; k < hashLength; k++)
vHash[k] ^= hash[k];
}
return isZero(vHash, sizeof(vHash));
}