Refactored keccak constants initialization

This commit is contained in:
SChernykh
2025-10-19 14:13:57 +02:00
parent baf13781e4
commit d8e4a00a32
4 changed files with 149 additions and 8 deletions

View File

@@ -162,7 +162,7 @@ struct alignas(uint64_t) hash
{
uint8_t h[HASH_SIZE];
FORCEINLINE hash() : h{} {}
FORCEINLINE constexpr hash() : h{} {}
constexpr hash(std::initializer_list<uint8_t> l) : h{} {
auto it = l.begin();

View File

@@ -17,6 +17,8 @@
#pragma once
#include "keccak_constexpr.h"
namespace p2pool {
enum KeccakParams {
@@ -26,12 +28,6 @@ enum KeccakParams {
extern const uint64_t keccakf_rndc[24];
// keccak hash of a single 0x00 byte
constexpr hash keccak_0x00{ 0xbc, 0x36, 0x78, 0x9e, 0x7a, 0x1e, 0x28, 0x14, 0x36, 0x46, 0x42, 0x29, 0x82, 0x8f, 0x81, 0x7d, 0x66, 0x12, 0xf7, 0xb4, 0x77, 0xd6, 0x65, 0x91, 0xff, 0x96, 0xa9, 0xe0, 0x64, 0xbc, 0xc9, 0x8a };
// keccak hash of "subaddress_viewpub"
constexpr hash keccak_subaddress_viewpub{ 0x40, 0xb2, 0x0e, 0x14, 0xc5, 0x9e, 0xdc, 0x32, 0x57, 0xb1, 0x71, 0xb0, 0xf3, 0x76, 0x27, 0x01, 0x8e, 0x92, 0x45, 0xed, 0xd5, 0x2a, 0x69, 0x0b, 0xf6, 0xd9, 0xe6, 0x21, 0xa0, 0x98, 0xb9, 0x6a };
typedef void (*keccakf_func)(std::array<uint64_t, 25>&);
extern keccakf_func keccakf;

144
src/keccak_constexpr.h Normal file
View File

@@ -0,0 +1,144 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021-2025 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace p2pool {
namespace ConstexprKeccak
{
template<int y>
static FORCEINLINE constexpr uint64_t rotl64(uint64_t x) { return (x << y) | (x >> (64 - y)); }
template<int ROUNDS>
static FORCEINLINE constexpr void keccakf(std::array<uint64_t, 25>& st)
{
constexpr uint64_t keccakf_rndc[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
};
for (int round = 0; round < ROUNDS; ++round) {
uint64_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) {
const uint64_t t = bc[(i + 4) % 5] ^ rotl64<1>(bc[(i + 1) % 5]);
for (int j = 0; j < 25; j += 5) st[i + j] ^= t;
}
// Rho Pi
const uint64_t st1 = st[1];
st[ 1] = rotl64<44>(st[ 6]);
st[ 6] = rotl64<20>(st[ 9]);
st[ 9] = rotl64<61>(st[22]);
st[22] = rotl64<39>(st[14]);
st[14] = rotl64<18>(st[20]);
st[20] = rotl64<62>(st[ 2]);
st[ 2] = rotl64<43>(st[12]);
st[12] = rotl64<25>(st[13]);
st[13] = rotl64< 8>(st[19]);
st[19] = rotl64<56>(st[23]);
st[23] = rotl64<41>(st[15]);
st[15] = rotl64<27>(st[ 4]);
st[ 4] = rotl64<14>(st[24]);
st[24] = rotl64< 2>(st[21]);
st[21] = rotl64<55>(st[ 8]);
st[ 8] = rotl64<45>(st[16]);
st[16] = rotl64<36>(st[ 5]);
st[ 5] = rotl64<28>(st[ 3]);
st[ 3] = rotl64<21>(st[18]);
st[18] = rotl64<15>(st[17]);
st[17] = rotl64<10>(st[11]);
st[11] = rotl64< 6>(st[ 7]);
st[ 7] = rotl64< 3>(st[10]);
st[10] = rotl64< 1>(st1);
// Chi
for (int i = 0; i < 25; i += 5) {
const uint64_t t[5] = { st[i], st[i + 1], st[i + 2], st[i + 3], st[i + 4] };
for (int j = 0; j < 5; ++j) st[i + j] ^= ~t[(j + 1) % 5] & t[(j + 2) % 5];
}
// Iota
st[0] ^= keccakf_rndc[round];
}
}
} // namespace ConstexprKeccak
template<int len>
static constexpr hash keccak(const char (&input)[len])
{
hash result{};
if constexpr (len <= 0) {
return result;
}
constexpr int inlen = len - 1;
constexpr int rsiz = 136;
constexpr int rsizw = rsiz / 8;
static_assert(inlen < rsiz, "Too long input");
uint8_t temp[144] = {};
for (int i = 0; i < inlen; ++i) {
temp[i] = static_cast<uint8_t>(input[i]);
}
temp[inlen] = 1;
temp[rsiz - 1] |= 0x80;
std::array<uint64_t, 25> st = {};
for (int i = 0; i < rsizw; i++) {
uint64_t k = 0;
for (int j = 0; j < 8; ++j) {
k |= static_cast<uint64_t>(temp[i * 8 + j]) << (j * 8);
}
st[i] ^= k;
}
ConstexprKeccak::keccakf<24>(st);
for (size_t i = 0; i < HASH_SIZE; ++i) {
result.h[i] = static_cast<uint8_t>(st[i / 8] >> ((i % 8) * 8));
}
return result;
}
constexpr hash keccak_0x00 = keccak("\0");
constexpr hash keccak_subaddress_viewpub = keccak("subaddress_viewpub");
constexpr hash keccak_onion_address_v3 = keccak("onion_address_v3");
static_assert((keccak_0x00.h[0] == 0xBC) && (keccak_0x00.h[1] == 0x36) && (keccak_0x00.h[2] == 0x78) && (keccak_0x00.h[3] == 0x9E), "constexpr keccak code check failed");
} // namespace p2pool

View File

@@ -240,7 +240,8 @@ void MergeMiningClientTari::on_external_block(const PoolBlock& block)
// Filter aux chain data only
for (const auto& i : block.m_mergeMiningExtra) {
if (i.first != keccak_subaddress_viewpub) {
if ((i.first != keccak_subaddress_viewpub) &&
(i.first != keccak_onion_address_v3)) {
mm_extra.emplace_back(i.first, i.second);
}
}