diff --git a/src/libethash/CMakeLists.txt b/src/libethash/CMakeLists.txt index 5fd19009..92c21d02 100644 --- a/src/libethash/CMakeLists.txt +++ b/src/libethash/CMakeLists.txt @@ -14,6 +14,7 @@ set(FILES util.h io.c internal.c progpow-internal.c + keccakf800.c ethash.h endian.h compiler.h diff --git a/src/libethash/internal.h b/src/libethash/internal.h index 6f045dc0..e9e8ba99 100644 --- a/src/libethash/internal.h +++ b/src/libethash/internal.h @@ -117,6 +117,7 @@ ethash_return_value_t ethash_light_compute_internal( ); void keccak_f800_round(uint32_t st[25], const int r); +void ethash_keccakf800(uint32_t st[25]); hash32_t keccak_f800_progpow(hash32_t header, uint64_t seed, hash32_t digest); uint32_t progpowMath(uint32_t a, uint32_t b, uint32_t r); void merge(uint32_t *a, uint32_t b, uint32_t r); diff --git a/src/libethash/keccakf800.c b/src/libethash/keccakf800.c new file mode 100644 index 00000000..89aaa486 --- /dev/null +++ b/src/libethash/keccakf800.c @@ -0,0 +1,235 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#include + +/*** Helper macros to unroll the permutation. ***/ +#define rol(x, s) (((x) << s) | ((x) >> (32 - s))) + +static const uint32_t RC[22] = { + 0x00000001, 0x00008082, 0x0000808A, + 0x80008000, 0x0000808B, 0x80000001, + 0x80008081, 0x00008009, 0x0000008A, + 0x00000088, 0x80008009, 0x8000000A, + 0x8000808B, 0x0000008B, 0x00008089, + 0x00008003, 0x00008002, 0x00000080, + 0x0000800A, 0x8000000A, 0x80008081, + 0x00008080, +}; + +/* The implementation directly translated from ethash_keccakf1600. by chfast */ +void ethash_keccakf800(uint32_t state[25]) +{ + uint32_t Aba, Abe, Abi, Abo, Abu; + uint32_t Aga, Age, Agi, Ago, Agu; + uint32_t Aka, Ake, Aki, Ako, Aku; + uint32_t Ama, Ame, Ami, Amo, Amu; + uint32_t Asa, Ase, Asi, Aso, Asu; + + uint32_t Eba, Ebe, Ebi, Ebo, Ebu; + uint32_t Ega, Ege, Egi, Ego, Egu; + uint32_t Eka, Eke, Eki, Eko, Eku; + uint32_t Ema, Eme, Emi, Emo, Emu; + uint32_t Esa, Ese, Esi, Eso, Esu; + + uint32_t Ba, Be, Bi, Bo, Bu; + + uint32_t Da, De, Di, Do, Du; + + int round; + + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < 22; round += 2) + { + /* Round (round + 0): Axx -> Exx */ + + Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + Be = Abe ^ Age ^ Ake ^ Ame ^ Ase; + Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Aba ^ Da; + Be = rol(Age ^ De, 12); + Bi = rol(Aki ^ Di, 11); + Bo = rol(Amo ^ Do, 21); + Bu = rol(Asu ^ Du, 14); + Eba = Ba ^ (~Be & Bi) ^ RC[round]; + Ebe = Be ^ (~Bi & Bo); + Ebi = Bi ^ (~Bo & Bu); + Ebo = Bo ^ (~Bu & Ba); + Ebu = Bu ^ (~Ba & Be); + + Ba = rol(Abo ^ Do, 28); + Be = rol(Agu ^ Du, 20); + Bi = rol(Aka ^ Da, 3); + Bo = rol(Ame ^ De, 13); + Bu = rol(Asi ^ Di, 29); + Ega = Ba ^ (~Be & Bi); + Ege = Be ^ (~Bi & Bo); + Egi = Bi ^ (~Bo & Bu); + Ego = Bo ^ (~Bu & Ba); + Egu = Bu ^ (~Ba & Be); + + Ba = rol(Abe ^ De, 1); + Be = rol(Agi ^ Di, 6); + Bi = rol(Ako ^ Do, 25); + Bo = rol(Amu ^ Du, 8); + Bu = rol(Asa ^ Da, 18); + Eka = Ba ^ (~Be & Bi); + Eke = Be ^ (~Bi & Bo); + Eki = Bi ^ (~Bo & Bu); + Eko = Bo ^ (~Bu & Ba); + Eku = Bu ^ (~Ba & Be); + + Ba = rol(Abu ^ Du, 27); + Be = rol(Aga ^ Da, 4); + Bi = rol(Ake ^ De, 10); + Bo = rol(Ami ^ Di, 15); + Bu = rol(Aso ^ Do, 24); + Ema = Ba ^ (~Be & Bi); + Eme = Be ^ (~Bi & Bo); + Emi = Bi ^ (~Bo & Bu); + Emo = Bo ^ (~Bu & Ba); + Emu = Bu ^ (~Ba & Be); + + Ba = rol(Abi ^ Di, 30); + Be = rol(Ago ^ Do, 23); + Bi = rol(Aku ^ Du, 7); + Bo = rol(Ama ^ Da, 9); + Bu = rol(Ase ^ De, 2); + Esa = Ba ^ (~Be & Bi); + Ese = Be ^ (~Bi & Bo); + Esi = Bi ^ (~Bo & Bu); + Eso = Bo ^ (~Bu & Ba); + Esu = Bu ^ (~Ba & Be); + + /* Round (round + 1): Exx -> Axx */ + + Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Eba ^ Da; + Be = rol(Ege ^ De, 12); + Bi = rol(Eki ^ Di, 11); + Bo = rol(Emo ^ Do, 21); + Bu = rol(Esu ^ Du, 14); + Aba = Ba ^ (~Be & Bi) ^ RC[round + 1]; + Abe = Be ^ (~Bi & Bo); + Abi = Bi ^ (~Bo & Bu); + Abo = Bo ^ (~Bu & Ba); + Abu = Bu ^ (~Ba & Be); + + Ba = rol(Ebo ^ Do, 28); + Be = rol(Egu ^ Du, 20); + Bi = rol(Eka ^ Da, 3); + Bo = rol(Eme ^ De, 13); + Bu = rol(Esi ^ Di, 29); + Aga = Ba ^ (~Be & Bi); + Age = Be ^ (~Bi & Bo); + Agi = Bi ^ (~Bo & Bu); + Ago = Bo ^ (~Bu & Ba); + Agu = Bu ^ (~Ba & Be); + + Ba = rol(Ebe ^ De, 1); + Be = rol(Egi ^ Di, 6); + Bi = rol(Eko ^ Do, 25); + Bo = rol(Emu ^ Du, 8); + Bu = rol(Esa ^ Da, 18); + Aka = Ba ^ (~Be & Bi); + Ake = Be ^ (~Bi & Bo); + Aki = Bi ^ (~Bo & Bu); + Ako = Bo ^ (~Bu & Ba); + Aku = Bu ^ (~Ba & Be); + + Ba = rol(Ebu ^ Du, 27); + Be = rol(Ega ^ Da, 4); + Bi = rol(Eke ^ De, 10); + Bo = rol(Emi ^ Di, 15); + Bu = rol(Eso ^ Do, 24); + Ama = Ba ^ (~Be & Bi); + Ame = Be ^ (~Bi & Bo); + Ami = Bi ^ (~Bo & Bu); + Amo = Bo ^ (~Bu & Ba); + Amu = Bu ^ (~Ba & Be); + + Ba = rol(Ebi ^ Di, 30); + Be = rol(Ego ^ Do, 23); + Bi = rol(Eku ^ Du, 7); + Bo = rol(Ema ^ Da, 9); + Bu = rol(Ese ^ De, 2); + Asa = Ba ^ (~Be & Bi); + Ase = Be ^ (~Bi & Bo); + Asi = Bi ^ (~Bo & Bu); + Aso = Bo ^ (~Bu & Ba); + Asu = Bu ^ (~Ba & Be); + } + + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} diff --git a/src/libethash/progpow-internal.c b/src/libethash/progpow-internal.c index e9981877..5963c37e 100644 --- a/src/libethash/progpow-internal.c +++ b/src/libethash/progpow-internal.c @@ -40,6 +40,11 @@ #include "sha3.h" #endif // WITH_CRYPTOPP +void ethash_keccakf800(uint32_t state[25]); + +// https://github.com/ifdefelse/ProgPOW#progpow-algorithm-walkthrough +#ifdef PROGPOW_0_9_2 +#define PROGPOW_PERIOD 50 #define PROGPOW_LANES 16 #define PROGPOW_REGS 32 #define PROGPOW_DAG_LOADS 4 @@ -47,8 +52,17 @@ #define PROGPOW_CNT_DAG ETHASH_ACCESSES #define PROGPOW_CNT_CACHE 12 #define PROGPOW_CNT_MATH 20 +#else // ProgPoW 0.9.3 +#define PROGPOW_PERIOD 10 +#define PROGPOW_LANES 16 +#define PROGPOW_REGS 32 +#define PROGPOW_DAG_LOADS 4 +#define PROGPOW_CACHE_BYTES (16*1024) +#define PROGPOW_CNT_DAG ETHASH_ACCESSES +#define PROGPOW_CNT_CACHE 11 +#define PROGPOW_CNT_MATH 18 +#endif #define PROGPOW_CACHE_WORDS (PROGPOW_CACHE_BYTES / sizeof(uint32_t)) -#define PROGPOW_PERIOD 50 #define ROTL(x,n,w) (((x) << (n % w)) | ((x) >> ((w) - (n % w)))) #define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ @@ -121,59 +135,6 @@ static inline uint32_t fnv1a(uint32_t *h, uint32_t d) return *h = (*h ^ d) * (uint32_t)0x1000193; } -// Implementation based on: -// https://github.com/mjosaarinen/tiny_sha3/blob/master/sha3.c -const uint32_t keccakf_rndc[24] = { - 0x00000001, 0x00008082, 0x0000808a, 0x80008000, 0x0000808b, 0x80000001, - 0x80008081, 0x00008009, 0x0000008a, 0x00000088, 0x80008009, 0x8000000a, - 0x8000808b, 0x0000008b, 0x00008089, 0x00008003, 0x00008002, 0x00000080, - 0x0000800a, 0x8000000a, 0x80008081, 0x00008080, 0x80000001, 0x80008008 -}; - -// Implementation of the permutation Keccakf with width 800. -void keccak_f800_round(uint32_t st[25], const int r) -{ - const uint32_t 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 uint32_t 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 - }; - - uint32_t t, bc[5]; - // Theta - for (int i = 0; i < 5; i++) - bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; - - for (int i = 0; i < 5; i++) { - t = bc[(i + 4) % 5] ^ ROTL32(bc[(i + 1) % 5], 1); - for (uint32_t j = 0; j < 25; j += 5) - st[j + i] ^= t; - } - - // Rho Pi - t = st[1]; - for (int i = 0; i < 24; i++) { - uint32_t j = keccakf_piln[i]; - bc[0] = st[j]; - st[j] = ROTL32(t, keccakf_rotc[i]); - t = bc[0]; - } - - // Chi - for (uint32_t j = 0; j < 25; j += 5) { - for (int i = 0; i < 5; i++) - bc[i] = st[j + i]; - for (int i = 0; i < 5; i++) - st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; - } - - // Iota - st[0] ^= keccakf_rndc[r]; -} - // Implementation of the Keccak sponge construction (with padding omitted) // The width is 800, with a bitrate of 576, and a capacity of 224. hash32_t keccak_f800_progpow(hash32_t header, uint64_t seed, hash32_t digest) @@ -189,11 +150,7 @@ hash32_t keccak_f800_progpow(hash32_t header, uint64_t seed, hash32_t digest) for (int i = 0; i < 8; i++) st[10+i] = digest.uint32s[i]; - for (int r = 0; r < 21; r++) { - keccak_f800_round(st, r); - } - // last round can be simplified due to partial output - keccak_f800_round(st, 21); + ethash_keccakf800(st); hash32_t ret; for (int i = 0; i < 8; i++) { diff --git a/src/libethash/sha3.c b/src/libethash/sha3.c index e72fe101..9013f4e6 100644 --- a/src/libethash/sha3.c +++ b/src/libethash/sha3.c @@ -1,11 +1,11 @@ /** libkeccak-tiny -* -* A single-file implementation of SHA-3 and SHAKE. -* -* Implementor: David Leon Gil -* License: CC0, attribution kindly requested. Blame taken too, -* but not liability. -*/ + * + * A single-file implementation of SHA-3 and SHAKE. + * + * Implementor: David Leon Gil + * License: CC0, attribution kindly requested. Blame taken too, + * but not liability. + */ #include "sha3.h" #include @@ -13,69 +13,241 @@ #include #include -/******** The Keccak-f[1600] permutation ********/ - -/*** Constants. ***/ -static const uint8_t rho[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}; -static const uint8_t pi[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}; -static const uint64_t RC[24] = \ - {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, - 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, - 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; +static const uint64_t RC[24] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, + 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL, + 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, + 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL, + 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL +}; /*** Helper macros to unroll the permutation. ***/ #define rol(x, s) (((x) << s) | ((x) >> (64 - s))) -#define REPEAT6(e) e e e e e e -#define REPEAT24(e) REPEAT6(e e e e) -#define REPEAT5(e) e e e e e -#define FOR5(v, s, e) \ - v = 0; \ - REPEAT5(e; v += s;) - -/*** Keccak-f[1600] ***/ -static inline void keccakf(void* state) { - uint64_t* a = (uint64_t*)state; - uint64_t b[5] = {0}; - uint64_t t = 0; - uint8_t x, y; - - for (int i = 0; i < 24; i++) { - // Theta - FOR5(x, 1, - b[x] = 0; - FOR5(y, 5, - b[x] ^= a[x + y]; )) - FOR5(x, 1, - FOR5(y, 5, - a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) - // Rho and pi - t = a[1]; - x = 0; - REPEAT24(b[0] = a[pi[x]]; - a[pi[x]] = rol(t, rho[x]); - t = b[0]; - x++; ) - // Chi - FOR5(y, - 5, - FOR5(x, 1, - b[x] = a[y + x];) - FOR5(x, 1, - a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) - // Iota - a[0] ^= RC[i]; - } + +/** + * keccakf1600 + * + * The implementation based on the "simple" implementation by Ronny Van Keer. + * from https://keccak.team/archives.html + * ref: https://github.com/chfast/ethash/blob/master/lib/keccak/keccakf1600.c + */ +static inline void keccakf(void* st) +{ + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + uint64_t Ba, Be, Bi, Bo, Bu; + + uint64_t Da, De, Di, Do, Du; + + int round; + + uint64_t *state = (uint64_t*)st; + + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < 24; round += 2) + { + /* Round (round + 0): Axx -> Exx */ + + Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + Be = Abe ^ Age ^ Ake ^ Ame ^ Ase; + Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Aba ^ Da; + Be = rol(Age ^ De, 44); + Bi = rol(Aki ^ Di, 43); + Bo = rol(Amo ^ Do, 21); + Bu = rol(Asu ^ Du, 14); + Eba = Ba ^ (~Be & Bi) ^ RC[round]; + Ebe = Be ^ (~Bi & Bo); + Ebi = Bi ^ (~Bo & Bu); + Ebo = Bo ^ (~Bu & Ba); + Ebu = Bu ^ (~Ba & Be); + + Ba = rol(Abo ^ Do, 28); + Be = rol(Agu ^ Du, 20); + Bi = rol(Aka ^ Da, 3); + Bo = rol(Ame ^ De, 45); + Bu = rol(Asi ^ Di, 61); + Ega = Ba ^ (~Be & Bi); + Ege = Be ^ (~Bi & Bo); + Egi = Bi ^ (~Bo & Bu); + Ego = Bo ^ (~Bu & Ba); + Egu = Bu ^ (~Ba & Be); + + Ba = rol(Abe ^ De, 1); + Be = rol(Agi ^ Di, 6); + Bi = rol(Ako ^ Do, 25); + Bo = rol(Amu ^ Du, 8); + Bu = rol(Asa ^ Da, 18); + Eka = Ba ^ (~Be & Bi); + Eke = Be ^ (~Bi & Bo); + Eki = Bi ^ (~Bo & Bu); + Eko = Bo ^ (~Bu & Ba); + Eku = Bu ^ (~Ba & Be); + + Ba = rol(Abu ^ Du, 27); + Be = rol(Aga ^ Da, 36); + Bi = rol(Ake ^ De, 10); + Bo = rol(Ami ^ Di, 15); + Bu = rol(Aso ^ Do, 56); + Ema = Ba ^ (~Be & Bi); + Eme = Be ^ (~Bi & Bo); + Emi = Bi ^ (~Bo & Bu); + Emo = Bo ^ (~Bu & Ba); + Emu = Bu ^ (~Ba & Be); + + Ba = rol(Abi ^ Di, 62); + Be = rol(Ago ^ Do, 55); + Bi = rol(Aku ^ Du, 39); + Bo = rol(Ama ^ Da, 41); + Bu = rol(Ase ^ De, 2); + Esa = Ba ^ (~Be & Bi); + Ese = Be ^ (~Bi & Bo); + Esi = Bi ^ (~Bo & Bu); + Eso = Bo ^ (~Bu & Ba); + Esu = Bu ^ (~Ba & Be); + + /* Round (round + 1): Exx -> Axx */ + + Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Eba ^ Da; + Be = rol(Ege ^ De, 44); + Bi = rol(Eki ^ Di, 43); + Bo = rol(Emo ^ Do, 21); + Bu = rol(Esu ^ Du, 14); + Aba = Ba ^ (~Be & Bi) ^ RC[round + 1]; + Abe = Be ^ (~Bi & Bo); + Abi = Bi ^ (~Bo & Bu); + Abo = Bo ^ (~Bu & Ba); + Abu = Bu ^ (~Ba & Be); + + Ba = rol(Ebo ^ Do, 28); + Be = rol(Egu ^ Du, 20); + Bi = rol(Eka ^ Da, 3); + Bo = rol(Eme ^ De, 45); + Bu = rol(Esi ^ Di, 61); + Aga = Ba ^ (~Be & Bi); + Age = Be ^ (~Bi & Bo); + Agi = Bi ^ (~Bo & Bu); + Ago = Bo ^ (~Bu & Ba); + Agu = Bu ^ (~Ba & Be); + + Ba = rol(Ebe ^ De, 1); + Be = rol(Egi ^ Di, 6); + Bi = rol(Eko ^ Do, 25); + Bo = rol(Emu ^ Du, 8); + Bu = rol(Esa ^ Da, 18); + Aka = Ba ^ (~Be & Bi); + Ake = Be ^ (~Bi & Bo); + Aki = Bi ^ (~Bo & Bu); + Ako = Bo ^ (~Bu & Ba); + Aku = Bu ^ (~Ba & Be); + + Ba = rol(Ebu ^ Du, 27); + Be = rol(Ega ^ Da, 36); + Bi = rol(Eke ^ De, 10); + Bo = rol(Emi ^ Di, 15); + Bu = rol(Eso ^ Do, 56); + Ama = Ba ^ (~Be & Bi); + Ame = Be ^ (~Bi & Bo); + Ami = Bi ^ (~Bo & Bu); + Amo = Bo ^ (~Bu & Ba); + Amu = Bu ^ (~Ba & Be); + + Ba = rol(Ebi ^ Di, 62); + Be = rol(Ego ^ Do, 55); + Bi = rol(Eku ^ Du, 39); + Bo = rol(Ema ^ Da, 41); + Bu = rol(Ese ^ De, 2); + Asa = Ba ^ (~Be & Bi); + Ase = Be ^ (~Bi & Bo); + Asi = Bi ^ (~Bo & Bu); + Aso = Bo ^ (~Bu & Ba); + Asu = Bu ^ (~Ba & Be); + } + + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; } /******** The FIPS202-defined functions. ********/ @@ -83,20 +255,20 @@ static inline void keccakf(void* state) { /*** Some helper macros. ***/ #define _(S) do { S } while (0) -#define FOR(i, ST, L, S) \ - _(for (size_t i = 0; i < L; i += ST) { S; }) -#define mkapply_ds(NAME, S) \ - static inline void NAME(uint8_t* dst, \ - const uint8_t* src, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } -#define mkapply_sd(NAME, S) \ - static inline void NAME(const uint8_t* src, \ - uint8_t* dst, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } +#define FOR(i, ST, L, S) \ + _(for (size_t i = 0; i < L; i += ST) { S; }) +#define mkapply_ds(NAME, S) \ + static inline void NAME(uint8_t* dst, \ + const uint8_t* src, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } +#define mkapply_sd(NAME, S) \ + static inline void NAME(const uint8_t* src, \ + uint8_t* dst, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } mkapply_ds(xorin, dst[i] ^= src[i]) // xorin mkapply_sd(setout, dst[i] = src[i]) // setout @@ -105,46 +277,47 @@ mkapply_sd(setout, dst[i] = src[i]) // setout #define Plen 200 // Fold P*F over the full blocks of an input. -#define foldP(I, L, F) \ - while (L >= rate) { \ - F(a, I, rate); \ - P(a); \ - I += rate; \ - L -= rate; \ - } +#define foldP(I, L, F) \ + while (L >= rate) { \ + F(a, I, rate); \ + P(a); \ + I += rate; \ + L -= rate; \ + } /** The sponge-based hash construction. **/ static inline int hash(uint8_t* out, size_t outlen, - const uint8_t* in, size_t inlen, - size_t rate, uint8_t delim) { - if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { - return -1; - } - uint8_t a[Plen] = {0}; - // Absorb input. - foldP(in, inlen, xorin); - // Xor in the DS and pad frame. - a[inlen] ^= delim; - a[rate - 1] ^= 0x80; - // Xor in the last block. - xorin(a, in, inlen); - // Apply P - P(a); - // Squeeze output. - foldP(out, outlen, setout); - setout(a, out, outlen); - memset(a, 0, 200); - return 0; + const uint8_t* in, size_t inlen, + size_t rate, uint8_t delim) { + if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { + return -1; + } + uint8_t a[Plen] = {0}; + // Absorb input. + foldP(in, inlen, xorin); + // Xor in the DS and pad frame. + a[inlen] ^= delim; + a[rate - 1] ^= 0x80; + // Xor in the last block. + xorin(a, in, inlen); + // Apply P + P(a); + // Squeeze output. + foldP(out, outlen, setout); + setout(a, out, outlen); + memset(a, 0, 200); + return 0; } -#define defsha3(bits) \ - int sha3_##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - if (outlen > (bits/8)) { \ - return -1; \ - } \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ - } +/*** Helper macros to define SHA3 and SHAKE instances. ***/ +#define defsha3(bits) \ + int sha3_##bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + if (outlen > (bits/8)) { \ + return -1; \ + } \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ + } /*** FIPS202 SHA3 FOFs ***/ defsha3(256) diff --git a/test/c/test_progpow.cpp b/test/c/test_progpow.cpp index 9742598b..2bf3d906 100644 --- a/test/c/test_progpow.cpp +++ b/test/c/test_progpow.cpp @@ -96,13 +96,6 @@ static ethash_h256_t stringToBlockhash(std::string const& _s) } /* ProgPoW */ - -static void ethash_keccakf800(uint32_t state[25]) -{ - for (int i = 0; i < 22; ++i) - keccak_f800_round(state, i); -} - BOOST_AUTO_TEST_CASE(test_progpow_math) { typedef struct { @@ -152,12 +145,12 @@ BOOST_AUTO_TEST_CASE(test_progpow_merge) mytest tests[] = { {1000000, 101, 33000101}, {2000000, 102, 66003366}, - {3000000, 103, 2999975}, - {4000000, 104, 4000104}, + {3000000, 103, 6000103}, + {4000000, 104, 2000104}, {1000000, 0, 33000000}, {2000000, 0, 66000000}, - {3000000, 0, 3000000}, - {4000000, 0, 4000000}, + {3000000, 0, 6000000}, + {4000000, 0, 2000000}, }; for (int i = 0; i < sizeof(tests) / sizeof(mytest); i++) { uint32_t res = tests[i].a; @@ -264,8 +257,8 @@ BOOST_AUTO_TEST_CASE(test_progpow_full_client_checks) { BOOST_REQUIRE(full_out.success); const std::string - exphead = "7ea12cfc33f64616ab7dbbddf3362ee7dd3e1e20d60d860a85c51d6559c912c4", - expmix = "a09ffaa0f2b5d47a98c2d4fbc0e90936710dd2b2a220fce04e8d55a6c6a093d6"; + exphead = "b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02", + expmix = "f4ac202715ded4136e72887c39e63a4738331c57fd9eb79f6ec421c281aa8743"; const std::string seed_string = blockhashToHexString(&seed); const std::string hash_string = blockhashToHexString(&hash); @@ -292,8 +285,8 @@ BOOST_AUTO_TEST_CASE(test_progpow_light_client_checks) { { uint64_t nonce = 0x0; const std::string - exphead = "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b", - expmix = "faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3"; + exphead = "b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02", + expmix = "f4ac202715ded4136e72887c39e63a4738331c57fd9eb79f6ec421c281aa8743"; const std::string hash_string = blockhashToHexString(&hash); light_out = progpow_light_compute_internal(light, full_size, hash, nonce, 0); @@ -324,41 +317,41 @@ struct progpow_hash_test_case progpow_hash_test_case progpow_hash_test_cases[] = { {0, "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000", - "faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3", - "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b"}, - {49, "63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b", "0000000006ff2c47", - "c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d", - "9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922"}, - {50, "9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922", "00000000076e482e", - "c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518", - "de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d"}, - {99, "de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d", "000000003917afab", - "f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7", - "ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce"}, - {29950, "ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce", "005d409dbc23a62a", - "07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e", - "e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5"}, - {29999, "e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5", "005db5fa4c2a3d03", - "7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8", - "d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454"}, - {30000, "d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454", "005db8607994ff30", - "f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4", - "8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64"}, - {30049, "8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64", "005e2e215a8ca2e7", - "57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add", - "c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047"}, - {30050, "c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047", "005e30899481055e", - "ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d", - "ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71"}, - {30099, "ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71", "005ea6aef136f88b", - "cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd", - "49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6"}, - {59950, "49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6", "02ebe0503bd7b1da", - "21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773", - "f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf"}, - {59999, "f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf", "02edb6275bd221e3", - "653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98", - "341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e88"}, + "f4ac202715ded4136e72887c39e63a4738331c57fd9eb79f6ec421c281aa8743", + "b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02"}, + {49, "b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02", "0000000006ff2c47", + "7730596f128f675ef9a6bb7281f268e4077d302f2b9078da1ece4349248561dd", + "0b9ed0c11157f1365143e329a6e1cea4248d9d6cb44b9c6daf492c7a076654a4"}, + {50, "0b9ed0c11157f1365143e329a6e1cea4248d9d6cb44b9c6daf492c7a076654a4", "00000000076e482e", + "829136d4a704eb8d06da773f1a90466e7b5ed12119c44526f045bbff4475d891", + "e2e881c5b893c2f1ef06b96a10cfcbcf7255b307f0818e7d30eb12b2edfc237b"}, + {99, "e2e881c5b893c2f1ef06b96a10cfcbcf7255b307f0818e7d30eb12b2edfc237b", "000000003917afab", + "deb3d8b45bdc596c56aa37a5eba456f478c82e60e5c028ce95f2e654e4bb7b57", + "9bdc2ad2286eaa051d6ca1f5196d2dd1c9a039f1d7ce3e1c856b793deed01778"}, + {29950, "9bdc2ad2286eaa051d6ca1f5196d2dd1c9a039f1d7ce3e1c856b793deed01778", "005d409dbc23a62a", + "c01e6d339cc687c77f653b81c74cb9de8b595554f2c5db671a7dde3846d2fa01", + "de0d693e597cf2fd70a4cfaa73f6baafc29e1eee695a81295b278c1116580b72"}, + {29999, "de0d693e597cf2fd70a4cfaa73f6baafc29e1eee695a81295b278c1116580b72", "005db5fa4c2a3d03", + "8b664cdbf396a7a185446c93dddd6611f5a736b11097381ae6bea45e802cec16", + "21ec5d1984a4fd4394b042aa96365085225d964727a45def245ceab326e28128"}, + {30000, "21ec5d1984a4fd4394b042aa96365085225d964727a45def245ceab326e28128", "005db8607994ff30", + "276951d89c1ed262bcac00df4fb9bf7af36991532744a2e287b0b758a56e15aa", + "dc070b76cc311cd82267f98936acbbbd3ec1c1ab25b55e2c885af6474e1e6841"}, + {30049, "dc070b76cc311cd82267f98936acbbbd3ec1c1ab25b55e2c885af6474e1e6841", "005e2e215a8ca2e7", + "6248ba0157d0f0592dacfe2963337948fffb37f67e7451a6862c1321d894cebe", + "6fdecf719e2547f585a6ee807d8237db8e9489f63d3f259ab5236451eaded433"}, + {30050, "6fdecf719e2547f585a6ee807d8237db8e9489f63d3f259ab5236451eaded433", "005e30899481055e", + "512d8f2bb0441fcfa1764c67e8dbed2afcbe9141de4bbebc5b51e0661dede550", + "cb1587a1c372642cbd9ce4c1ba2f433985d44c571a676a032bc1e8c1ad066e24"}, + {30099, "cb1587a1c372642cbd9ce4c1ba2f433985d44c571a676a032bc1e8c1ad066e24", "005ea6aef136f88b", + "be0e7d6afa6edd483ccc304afa9bf0abaca5e0f037a4f05bf5550b9309d1d12c", + "78be18f20569a834d839dad48e0e51d6df6b6537575f0ad29898c7cf357f12cb"}, + {59950, "78be18f20569a834d839dad48e0e51d6df6b6537575f0ad29898c7cf357f12cb", "02ebe0503bd7b1da", + "b85be51fce670aa437f28c02ea4fd7995fa8b6ac224e959b8dbfb5bdbc6f77ce", + "a68a620ba17e0cf2817bc4397cf4b85f5770983aa7b7931319a7f61bd6f905b1"}, + {59999, "a68a620ba17e0cf2817bc4397cf4b85f5770983aa7b7931319a7f61bd6f905b1", "02edb6275bd221e3", + "ffe745a932c21c0704291bb416fe8bffec76621cd3434861885beab42cec1734", + "9e6667a151ac6f5186a05cb20877a2b3df02317046256a762cb8ec2d96aa34f0"}, }; BOOST_AUTO_TEST_CASE(test_progpow_test_cases) {