Skip to content

Commit

Permalink
equihash: Pass blake2b_simd bindings to Tromp solver as callbacks
Browse files Browse the repository at this point in the history
This avoids linker errors by removing cycles.
  • Loading branch information
str4d committed Jan 4, 2024
1 parent 7e35cb9 commit b5896f5
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 66 deletions.
10 changes: 5 additions & 5 deletions components/equihash/tromp/blake2b.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ typedef struct BLAKE2bState BLAKE2bState;
/// `personalization` MUST be a pointer to a 16-byte array.
///
/// Please free this with `blake2b_free` when you are done.
BLAKE2bState* blake2b_init(
typedef BLAKE2bState* (*blake2b_init)(
size_t output_len,
const unsigned char* personalization);

/// Clones the given BLAKE2b state.
///
/// Both states need to be separately freed with `blake2b_free` when you are
/// done.
BLAKE2bState* blake2b_clone(const BLAKE2bState* state);
typedef BLAKE2bState* (*blake2b_clone)(const BLAKE2bState* state);

/// Frees a BLAKE2b state returned by `blake2b_init`.
void blake2b_free(BLAKE2bState* state);
typedef void (*blake2b_free)(BLAKE2bState* state);

/// Adds input to the hash. You can call this any number of times.
void blake2b_update(
typedef void (*blake2b_update)(
BLAKE2bState* state,
const unsigned char* input,
size_t input_len);
Expand All @@ -43,7 +43,7 @@ void blake2b_update(
/// This method is idempotent, and calling it multiple times will give the same
/// result. It's also possible to call `blake2b_update` with more input in
/// between.
void blake2b_finalize(
typedef void (*blake2b_finalize)(
BLAKE2bState* state,
unsigned char* output,
size_t output_len);
Expand Down
54 changes: 0 additions & 54 deletions components/equihash/tromp/equi.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,63 +43,9 @@ typedef u32 proof[PROOFSIZE];
enum verify_code { POW_OK, POW_DUPLICATE, POW_OUT_OF_ORDER, POW_NONZERO_XOR };
const char *errstr[] = { "OK", "duplicate index", "indices out of order", "nonzero xor" };

void genhash(const BLAKE2bState *ctx, u32 idx, uchar *hash) {
BLAKE2bState* state = blake2b_clone(ctx);
u32 leb = htole32(idx / HASHESPERBLAKE);
blake2b_update(state, (uchar *)&leb, sizeof(u32));
uchar blakehash[HASHOUT];
blake2b_finalize(state, blakehash, HASHOUT);
blake2b_free(state);
memcpy(hash, blakehash + (idx % HASHESPERBLAKE) * WN/8, WN/8);
}

int verifyrec(const BLAKE2bState *ctx, u32 *indices, uchar *hash, int r) {
if (r == 0) {
genhash(ctx, *indices, hash);
return POW_OK;
}
u32 *indices1 = indices + (1 << (r-1));
if (*indices >= *indices1)
return POW_OUT_OF_ORDER;
uchar hash0[WN/8], hash1[WN/8];
int vrf0 = verifyrec(ctx, indices, hash0, r-1);
if (vrf0 != POW_OK)
return vrf0;
int vrf1 = verifyrec(ctx, indices1, hash1, r-1);
if (vrf1 != POW_OK)
return vrf1;
for (int i=0; i < WN/8; i++)
hash[i] = hash0[i] ^ hash1[i];
int i, b = r * DIGITBITS;
for (i = 0; i < b/8; i++)
if (hash[i])
return POW_NONZERO_XOR;
if ((b%8) && hash[i] >> (8-(b%8)))
return POW_NONZERO_XOR;
return POW_OK;
}

int compu32(const void *pa, const void *pb) {
u32 a = *(u32 *)pa, b = *(u32 *)pb;
return a<b ? -1 : a==b ? 0 : +1;
}

bool duped(proof prf) {
proof sortprf;
memcpy(sortprf, prf, sizeof(proof));
qsort(sortprf, PROOFSIZE, sizeof(u32), &compu32);
for (u32 i=1; i<PROOFSIZE; i++)
if (sortprf[i] <= sortprf[i-1])
return true;
return false;
}

// verify Wagner conditions
int verify(u32 indices[PROOFSIZE], const BLAKE2bState *ctx) {
if (duped(indices))
return POW_DUPLICATE;
uchar hash[WN/8];
return verifyrec(ctx, indices, hash, WK);
}

#endif // ZCASH_POW_TROMP_EQUI_H
28 changes: 21 additions & 7 deletions components/equihash/tromp/equi_miner.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ u32 min(const u32 a, const u32 b) {

struct equi {
BLAKE2bState* blake_ctx;
blake2b_clone blake2b_clone;
blake2b_free blake2b_free;
blake2b_update blake2b_update;
blake2b_finalize blake2b_finalize;
htalloc hta;
bsizes *nslots; // PUT IN BUCKET STRUCT
proof *sols;
Expand All @@ -231,10 +235,20 @@ struct equi {
pthread_barrier_t barry;
};
typedef struct equi equi;
equi *equi_new(const u32 n_threads) {
equi *equi_new(
const u32 n_threads,
blake2b_clone blake2b_clone,
blake2b_free blake2b_free,
blake2b_update blake2b_update,
blake2b_finalize blake2b_finalize
) {
assert(sizeof(hashunit) == 4);
equi *eq = malloc(sizeof(equi));
eq->nthreads = n_threads;
eq->blake2b_clone = blake2b_clone;
eq->blake2b_free = blake2b_free;
eq->blake2b_update = blake2b_update;
eq->blake2b_finalize = blake2b_finalize;
const int err = pthread_barrier_init(&eq->barry, NULL, eq->nthreads);
assert(!err);
alloctrees(eq->hta);
Expand All @@ -246,11 +260,11 @@ typedef struct equi equi;
dealloctrees(eq->hta);
free(eq->nslots);
free(eq->sols);
blake2b_free(eq->blake_ctx);
eq->blake2b_free(eq->blake_ctx);
free(eq);
}
void equi_setstate(equi *eq, const BLAKE2bState *ctx) {
eq->blake_ctx = blake2b_clone(ctx);
eq->blake_ctx = eq->blake2b_clone(ctx);
memset(eq->nslots, 0, NBUCKETS * sizeof(au32)); // only nslots[0] needs zeroing
eq->nsols = 0;
}
Expand Down Expand Up @@ -464,11 +478,11 @@ typedef struct equi equi;
htlayout htl = htlayout_new(eq, 0);
const u32 hashbytes = hashsize(0);
for (u32 block = id; block < NBLOCKS; block += eq->nthreads) {
state = blake2b_clone(eq->blake_ctx);
state = eq->blake2b_clone(eq->blake_ctx);
u32 leb = htole32(block);
blake2b_update(state, (uchar *)&leb, sizeof(u32));
blake2b_finalize(state, hash, HASHOUT);
blake2b_free(state);
eq->blake2b_update(state, (uchar *)&leb, sizeof(u32));
eq->blake2b_finalize(state, hash, HASHOUT);
eq->blake2b_free(state);
for (u32 i = 0; i<HASHESPERBLAKE; i++) {
const uchar *ph = hash + i * WN/8;
#if BUCKBITS == 16 && RESTBITS == 4
Expand Down

0 comments on commit b5896f5

Please sign in to comment.