Skip to content
Merged
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
26 changes: 22 additions & 4 deletions .github/workflows/unit_test_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,35 @@ jobs:

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
# Explicit allowlist of the hermetic (no-GPU) suites compiled in this
# NVIDIA/AMD/CPU-OFF build. Excludes the GPU device resolvers
# (Resolver*NvidiaTest / Resolver*AmdTest) and the OpenCL/CPU-gated KATs,
# which aren't compiled here.
TEST_FILTER: >-
AlgoTypeTest.*:
AutolykosV2CpuShare.*:
Bitwise.*:
Blake3Ref.*:
EthashTest.*:
FastModTest.*:
Fnv.*:
Fnv1Test.*:
HashTest.*:
Kiss.*:
KHeavyHashHeavyHash.*:
KHeavyHashKHeavyHash.*:
KHeavyHashMatrix.*:
KHeavyHashPowHash.*:
Kiss99Test.*:
MathTest.*:
ProgpowKernelOpenCLTest.*:
RotateByteTest.*:
StratumEthashSubmitNonce.*:
StratumProgpowSeed.*
StatisticalHashrate.*:
StratumAutolykosV2NotifyTest.*:
StratumBlake3ProtocolTest.*:
StratumEthashAuthorizeTest.*:
StratumEthashSubmitNonceTest.*:
StratumMath.*:
StratumProgpowSeed.*:
WritePump.*

steps:
- uses: actions/checkout@v4
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,6 @@ dist/
# build-output ignores above (x64/, arm64/). These are tracked source, not build
# output, so re-include them.
!.github/actions/**

# AI
.claude
10 changes: 10 additions & 0 deletions sources/algo/bitwise.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ namespace algo
return le::uint64(word);
}

// Little-endian store of 4 u64 words into a 32-byte buffer.
inline void store256(uint8_t* const data, uint64_t const* const words)
{
for (uint32_t w{ 0u }; w < 4u; ++w)
{
uint64_t const word{ le::uint64(words[w]) };
__builtin_memcpy(data + w * sizeof(uint64_t), &word, sizeof(uint64_t));
}
}

inline hash1024 const& uint32(algo::hash1024 const& h)
{
return h;
Expand Down
13 changes: 13 additions & 0 deletions sources/algo/hash_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ namespace algo
return true;
}

template<typename T>
inline bool isLowerOrEqualLE(T const& value, T const& target)
{
for (int64_t i{ cast64(sizeof(T)) - 1 }; i >= 0; --i)
{
if (value.ubytes[i] != target.ubytes[i])
{
return value.ubytes[i] < target.ubytes[i];
}
}
return true;
}

template<typename T>
inline void copyHash(T& dst, T const& src)
{
Expand Down
226 changes: 2 additions & 224 deletions sources/algo/keccak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,228 +9,6 @@
constexpr uint32_t F800_NUMBER_ROUND{ 22u };


static inline void keccak_f1600(uint64_t* const state)
{
constexpr uint64_t roundConstants[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
};

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;

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 (size_t n = 0; n < 24; n += 2)
{
// Round (n + 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 ^ algo::rol_u64(Be, 1);
De = Ba ^ algo::rol_u64(Bi, 1);
Di = Be ^ algo::rol_u64(Bo, 1);
Do = Bi ^ algo::rol_u64(Bu, 1);
Du = Bo ^ algo::rol_u64(Ba, 1);

Ba = Aba ^ Da;
Be = algo::rol_u64(Age ^ De, 44);
Bi = algo::rol_u64(Aki ^ Di, 43);
Bo = algo::rol_u64(Amo ^ Do, 21);
Bu = algo::rol_u64(Asu ^ Du, 14);
Eba = Ba ^ (~Be & Bi) ^ roundConstants[n];
Ebe = Be ^ (~Bi & Bo);
Ebi = Bi ^ (~Bo & Bu);
Ebo = Bo ^ (~Bu & Ba);
Ebu = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Abo ^ Do, 28);
Be = algo::rol_u64(Agu ^ Du, 20);
Bi = algo::rol_u64(Aka ^ Da, 3);
Bo = algo::rol_u64(Ame ^ De, 45);
Bu = algo::rol_u64(Asi ^ Di, 61);
Ega = Ba ^ (~Be & Bi);
Ege = Be ^ (~Bi & Bo);
Egi = Bi ^ (~Bo & Bu);
Ego = Bo ^ (~Bu & Ba);
Egu = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Abe ^ De, 1);
Be = algo::rol_u64(Agi ^ Di, 6);
Bi = algo::rol_u64(Ako ^ Do, 25);
Bo = algo::rol_u64(Amu ^ Du, 8);
Bu = algo::rol_u64(Asa ^ Da, 18);
Eka = Ba ^ (~Be & Bi);
Eke = Be ^ (~Bi & Bo);
Eki = Bi ^ (~Bo & Bu);
Eko = Bo ^ (~Bu & Ba);
Eku = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Abu ^ Du, 27);
Be = algo::rol_u64(Aga ^ Da, 36);
Bi = algo::rol_u64(Ake ^ De, 10);
Bo = algo::rol_u64(Ami ^ Di, 15);
Bu = algo::rol_u64(Aso ^ Do, 56);
Ema = Ba ^ (~Be & Bi);
Eme = Be ^ (~Bi & Bo);
Emi = Bi ^ (~Bo & Bu);
Emo = Bo ^ (~Bu & Ba);
Emu = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Abi ^ Di, 62);
Be = algo::rol_u64(Ago ^ Do, 55);
Bi = algo::rol_u64(Aku ^ Du, 39);
Bo = algo::rol_u64(Ama ^ Da, 41);
Bu = algo::rol_u64(Ase ^ De, 2);
Esa = Ba ^ (~Be & Bi);
Ese = Be ^ (~Bi & Bo);
Esi = Bi ^ (~Bo & Bu);
Eso = Bo ^ (~Bu & Ba);
Esu = Bu ^ (~Ba & Be);


// Round (n + 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 ^ algo::rol_u64(Be, 1);
De = Ba ^ algo::rol_u64(Bi, 1);
Di = Be ^ algo::rol_u64(Bo, 1);
Do = Bi ^ algo::rol_u64(Bu, 1);
Du = Bo ^ algo::rol_u64(Ba, 1);

Ba = Eba ^ Da;
Be = algo::rol_u64(Ege ^ De, 44);
Bi = algo::rol_u64(Eki ^ Di, 43);
Bo = algo::rol_u64(Emo ^ Do, 21);
Bu = algo::rol_u64(Esu ^ Du, 14);
Aba = Ba ^ (~Be & Bi) ^ roundConstants[n + 1];
Abe = Be ^ (~Bi & Bo);
Abi = Bi ^ (~Bo & Bu);
Abo = Bo ^ (~Bu & Ba);
Abu = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Ebo ^ Do, 28);
Be = algo::rol_u64(Egu ^ Du, 20);
Bi = algo::rol_u64(Eka ^ Da, 3);
Bo = algo::rol_u64(Eme ^ De, 45);
Bu = algo::rol_u64(Esi ^ Di, 61);
Aga = Ba ^ (~Be & Bi);
Age = Be ^ (~Bi & Bo);
Agi = Bi ^ (~Bo & Bu);
Ago = Bo ^ (~Bu & Ba);
Agu = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Ebe ^ De, 1);
Be = algo::rol_u64(Egi ^ Di, 6);
Bi = algo::rol_u64(Eko ^ Do, 25);
Bo = algo::rol_u64(Emu ^ Du, 8);
Bu = algo::rol_u64(Esa ^ Da, 18);
Aka = Ba ^ (~Be & Bi);
Ake = Be ^ (~Bi & Bo);
Aki = Bi ^ (~Bo & Bu);
Ako = Bo ^ (~Bu & Ba);
Aku = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Ebu ^ Du, 27);
Be = algo::rol_u64(Ega ^ Da, 36);
Bi = algo::rol_u64(Eke ^ De, 10);
Bo = algo::rol_u64(Emi ^ Di, 15);
Bu = algo::rol_u64(Eso ^ Do, 56);
Ama = Ba ^ (~Be & Bi);
Ame = Be ^ (~Bi & Bo);
Ami = Bi ^ (~Bo & Bu);
Amo = Bo ^ (~Bu & Ba);
Amu = Bu ^ (~Ba & Be);

Ba = algo::rol_u64(Ebi ^ Di, 62);
Be = algo::rol_u64(Ego ^ Do, 55);
Bi = algo::rol_u64(Eku ^ Du, 39);
Bo = algo::rol_u64(Ema ^ Da, 41);
Bu = algo::rol_u64(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;
}


void algo::keccak(uint64_t* const out, uint32_t bits, uint8_t const* data, uint32_t size)
{
constexpr size_t wordSize{ sizeof(uint64_t) };
Expand All @@ -250,7 +28,7 @@ void algo::keccak(uint64_t* const out, uint32_t bits, uint8_t const* data, uint3
state[i] ^= le::uint64(data);
data += wordSize;
}
keccak_f1600(state);
keccakF1600(state);
size -= blockSize;
}

Expand All @@ -276,7 +54,7 @@ void algo::keccak(uint64_t* const out, uint32_t bits, uint8_t const* data, uint3

state[(blockSize / wordSize) - 1] ^= 0x8000000000000000;

keccak_f1600(state);
keccakF1600(state);

uint32_t const maxIndex{ hashSize / castU32(wordSize) };
for (uint32_t i{ 0u }; i < maxIndex; ++i)
Expand Down
Loading
Loading