Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Progpow 0.9.3 #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libethash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ set(FILES util.h
io.c
internal.c
progpow-internal.c
keccakf800.c
ethash.h
endian.h
compiler.h
Expand Down
1 change: 1 addition & 0 deletions src/libethash/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
235 changes: 235 additions & 0 deletions src/libethash/keccakf800.c
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>

/*** 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;
}
75 changes: 16 additions & 59 deletions src/libethash/progpow-internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,29 @@
#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
#define PROGPOW_CACHE_BYTES (16*1024)
#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 */
Expand Down Expand Up @@ -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)
Expand All @@ -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++) {
Expand Down
Loading