build cache with Argon2d

This commit is contained in:
wowario
2025-09-23 01:14:09 +03:00
parent c09ff73c9f
commit 5ffd4407b4
3 changed files with 32 additions and 72 deletions
+27 -34
View File
@@ -1,8 +1,8 @@
//
// Wownero Blake-AES-Groestl ("WBAG")
// Wownero Blake-Argon2d-Groestl ("WBAG")
//
// Memory-hard hash function that combines BLAKE256 and Groestl256 using hardware-accelerated AES
// - Cache: parameterized, power-of-two, default 256 MiB of 64-byte entries derived via BLAKE256
// Memory-hard hash function that combines BLAKE256, Argon2d, and Groestl256 using hardware-accelerated AES
// - Cache: Argon2d-derived buffer of size WBAG_CACHE_BYTES (default 256 MiB)
// - Prehash: st = BLAKE256('m' || bd), parsed as four 64-bit little-endian lanes
// - Rounds: data-dependent cache index, XOR entry words into lanes, rotate by SplitMix64-derived counts,
// then one AES round per 128-bit pair (two total) using w0..w3 as the round keys
@@ -43,6 +43,7 @@
#include "wbag-hash.h"
#include "blake256.h"
#include "argon2/argon2.h"
#include "aesb.h"
#include "groestl.h"
@@ -69,6 +70,14 @@ int WBAG_get_aes_mode(void) { return g_wbag_aes_mode; }
#define WBAG_N_ENTRIES ( (WBAG_CACHE_BYTES / WBAG_ENTRY_BYTES) )
#ifndef WBAG_ARGON2_P
#define WBAG_ARGON2_P 2u //threads
#endif
#ifndef WBAG_ARGON2_T
#define WBAG_ARGON2_T 1u // passes
#endif
_Static_assert(WBAG_ARGON2_P == 2u, "WBAG requires Argon2 p=2");
// Upper bound to mitigate large-input in WBAG_hash() allocation
#ifndef WBAG_MAX_BD_LEN
#define WBAG_MAX_BD_LEN (16u * 1024u * 1024u) // 16 MiB
@@ -186,13 +195,12 @@ static inline uint64_t WBAG_splitmix64(uint64_t x) {
// 32-bit FNV-1a over the textual description of params
uint32_t WBAG_params_signature(void) {
char buf[96];
char buf[160];
int n = snprintf(buf, sizeof(buf),
"cache=%zu;entry=%zu;entries=%zu;rounds=%u",
(size_t)WBAG_CACHE_BYTES,
(size_t)WBAG_ENTRY_BYTES,
(size_t)WBAG_N_ENTRIES,
(unsigned)WBAG_ROUNDS);
"cache=%zu;entry=%zu;entries=%zu;rounds=%u;cache_prf=argon2d;ver=0x%02x;t=%u;p=%u",
(size_t)WBAG_CACHE_BYTES, (size_t)WBAG_ENTRY_BYTES, (size_t)WBAG_N_ENTRIES,
(unsigned)WBAG_ROUNDS, (unsigned)ARGON2_VERSION_13,
(unsigned)WBAG_ARGON2_T, (unsigned)WBAG_ARGON2_P);
if (n < 0) n = 0;
if (n >= (int)sizeof(buf)) n = (int)sizeof(buf) - 1;
@@ -286,35 +294,20 @@ void WBAG_epoch_seed(uint64_t epoch, const uint8_t anchor_hash[32], uint8_t out3
}
// Cache builder
void WBAG_build_cache(const uint8_t seed32[32], uint8_t *out_base, uint64_t start, uint64_t end)
int WBAG_build_cache(const uint8_t seed32[32], uint8_t *out_base)
{
if (!seed32 || !out_base) return;
if (start >= end) return;
if (end > (uint64_t)WBAG_N_ENTRIES) return;
if (!seed32 || !out_base) return -1;
enum { IN_LEN = 32 + 4 + 4 };
uint8_t in[IN_LEN];
memcpy(in, seed32, 32);
const uint32_t m_cost_kib = (uint32_t)(WBAG_CACHE_BYTES / 1024u);
const uint32_t p = WBAG_ARGON2_P;
const uint32_t t_cost = (uint32_t)WBAG_ARGON2_T;
const size_t eb = (size_t)WBAG_ENTRY_BYTES;
uint8_t *base = out_base + (size_t)start * eb;
for (uint64_t i = start; i < end; i++) {
uint8_t *entry = base + (size_t)(i - start) * eb;
WBAG_store32_le(&in[32], (uint32_t)i);
size_t written = 0;
uint32_t blk = 0;
uint8_t out[32];
while (written < eb) {
WBAG_store32_le(&in[36], blk++);
blake256_hash(out, in, (uint64_t)IN_LEN);
size_t take = eb - written;
if (take > 32) take = 32;
memcpy(entry + written, out, take);
written += take;
}
int rc = argon2_hash(t_cost, m_cost_kib, p, seed32, 32, "WBAG-cache", 10, out_base, (size_t)WBAG_CACHE_BYTES, NULL, 0, Argon2_d, ARGON2_VERSION_13);
if (rc != ARGON2_OK) {
memset(out_base, 0, (size_t)WBAG_CACHE_BYTES);
return rc;
}
return 0;
}
// Hash: prehash, rounds with AES mix, Groestl finalize
+2 -1
View File
@@ -12,7 +12,8 @@ void WBAG_set_aes_mode(int mode);
int WBAG_get_aes_mode(void);
void WBAG_epoch_seed(uint64_t epoch, const uint8_t anchor_hash[32], uint8_t out32[32]);
void WBAG_build_cache(const uint8_t seed[32], uint8_t *out_base, uint64_t start, uint64_t end);
int WBAG_build_cache(const uint8_t seed32[32], uint8_t *out_base);
int WBAG_hash(const void *bd, size_t bd_len, const uint8_t *cache, uint8_t out32[32]);
+3 -37
View File
@@ -14,7 +14,6 @@
#include <limits>
#include <string>
#include <cstdint>
#include <thread>
#include "misc_log_ex.h"
#include "string_tools.h"
@@ -47,15 +46,8 @@ inline bool cache_matches(uint64_t e, const crypto::hash &ah) {
return p && p->epoch == e && p->anchor_hash == ah;
}
// Build threads; 2 threads by default
static std::atomic<unsigned> g_build_threads{2};
} // namespace
void set_build_threads(unsigned t) noexcept {
g_build_threads.store(t, std::memory_order_relaxed);
}
bool ensure_cache(uint64_t e, const crypto::hash &ah)
{
if (cache_matches(e, ah))
@@ -109,36 +101,10 @@ bool ensure_cache(uint64_t e, const crypto::hash &ah)
alignas(64) uint8_t seed[32];
epoch_seed_from_anchor(e, ah, seed);
unsigned req = g_build_threads.load(std::memory_order_relaxed);
unsigned hw = std::thread::hardware_concurrency();
if (hw == 0) hw = 1;
unsigned T = req ? req : hw;
if (T < 1) T = 1;
const uint64_t n_entries = n;
if (T > n_entries) T = static_cast<unsigned>(n_entries);
std::atomic<bool> failed{false};
if (T == 1) {
WBAG_build_cache(seed, fresh->data.data(), 0, n_entries);
} else {
std::vector<std::thread> workers;
workers.reserve(T);
for (unsigned i = 0; i < T; ++i) {
const uint64_t start = (static_cast<uint64_t>(i) * n_entries) / T;
const uint64_t end = (static_cast<uint64_t>(i + 1) * n_entries) / T;
workers.emplace_back([&, start, end]() noexcept {
try {
WBAG_build_cache(seed, fresh->data.data(), start, end);
} catch (...) {
failed.store(true, std::memory_order_relaxed);
}
});
}
for (auto &t : workers) { try { t.join(); } catch (...) { failed.store(true, std::memory_order_relaxed); } }
if (failed.load(std::memory_order_relaxed)) {
MERROR("WBAG parallel build failed; not publishing" << " (epoch=" << e << ", anchor=" << anchor_hex << ")");
return false;
}
if (WBAG_build_cache(seed, fresh->data.data()) != 0) {
MERROR("WBAG Argon2d cache build failed" << " (epoch=" << e << ", anchor=" << anchor_hex << ")");
return false;
}
// final re-check to avoid duplicate publish