upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/randomx_pow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/randomx_pow.cpp')
-rw-r--r--src/randomx_pow.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/randomx_pow.cpp b/src/randomx_pow.cpp
new file mode 100644
index 0000000..17bf455
--- /dev/null
+++ b/src/randomx_pow.cpp
@@ -0,0 +1,143 @@
1// Copyright (c) 2026 Bitflash developers
2// Distributed under the MIT/X11 software license.
3//
4// RandomX PoW implementation. See randomx_pow.h.
5
6#include "headers.h"
7#include <randomx.h>
8#include <thread>
9#include <vector>
10
11// Fixed key (seed) that determines the RandomX cache/dataset. Keeping it
12// constant avoids per-epoch "reseed" logic; for the CPU+RAM fairness goal
13// this is sufficient (RandomX already neutralizes GPU/ASIC by design).
14static const char* RANDOMX_KEY = "Bitflash/RandomX/v1/one-cpu-one-vote";
15
16static randomx_flags g_flags = RANDOMX_FLAG_DEFAULT;
17static randomx_cache* g_cache = NULL;
18static randomx_dataset* g_dataset = NULL;
19static randomx_vm* g_vmVerify = NULL;
20static CCriticalSection g_csVerify;
21static bool g_fInit = false;
22static bool g_fFast = false;
23
24
25bool RandomXInit()
26{
27 if (g_fInit)
28 return true;
29
30 // Detect the best flags for this CPU (JIT, hardware AES, Argon2).
31 g_flags = randomx_get_flags();
32
33 g_cache = randomx_alloc_cache(g_flags);
34 if (!g_cache)
35 {
36 // Try without JIT as a fallback
37 g_flags = RANDOMX_FLAG_DEFAULT;
38 g_cache = randomx_alloc_cache(g_flags);
39 if (!g_cache)
40 return error("RandomX: failed to allocate cache (256 MB)");
41 }
42 randomx_init_cache(g_cache, RANDOMX_KEY, strlen(RANDOMX_KEY));
43
44 // Verification VM in light mode (cache only)
45 g_vmVerify = randomx_create_vm(g_flags, g_cache, NULL);
46 if (!g_vmVerify)
47 return error("RandomX: failed to create verification VM");
48
49 g_fInit = true;
50 printf("RandomX: initialized (cache 256 MB, flags=%d)\n", (int)g_flags);
51 return true;
52}
53
54
55bool RandomXInitDataset(int nThreads)
56{
57 if (!g_fInit && !RandomXInit())
58 return false;
59 if (g_fFast)
60 return true;
61
62 randomx_flags fastFlags = (randomx_flags)(g_flags | RANDOMX_FLAG_FULL_MEM);
63 g_dataset = randomx_alloc_dataset(fastFlags);
64 if (!g_dataset)
65 {
66 printf("RandomX: not enough memory for the 2 GB dataset, staying in light mode\n");
67 return false;
68 }
69
70 unsigned long total = randomx_dataset_item_count();
71 if (nThreads < 1) nThreads = 1;
72 printf("RandomX: initializing ~2 GB dataset with %d threads...\n", nThreads);
73
74 std::vector<std::thread> workers;
75 unsigned long per = total / nThreads;
76 for (int i = 0; i < nThreads; i++)
77 {
78 unsigned long start = i * per;
79 unsigned long count = (i == nThreads - 1) ? (total - start) : per;
80 workers.emplace_back([start, count]() {
81 randomx_init_dataset(g_dataset, g_cache, start, count);
82 });
83 }
84 for (auto& w : workers) w.join();
85
86 g_fFast = true;
87 printf("RandomX: dataset ready (fast mode active)\n");
88 return true;
89}
90
91
92bool RandomXFastReady()
93{
94 return g_fFast;
95}
96
97
98uint256 RandomXPoWHash(const void* pHeader, size_t nSize)
99{
100 uint256 result = 0;
101 if (!g_fInit && !RandomXInit())
102 return result;
103 CRITICAL_BLOCK(g_csVerify)
104 {
105 unsigned char hash[RANDOMX_HASH_SIZE];
106 randomx_calculate_hash(g_vmVerify, pHeader, nSize, hash);
107 memcpy(&result, hash, RANDOMX_HASH_SIZE);
108 }
109 return result;
110}
111
112
113void* RandomXCreateMinerVM()
114{
115 if (!g_fInit && !RandomXInit())
116 return NULL;
117 if (g_fFast && g_dataset)
118 {
119 randomx_flags fastFlags = (randomx_flags)(g_flags | RANDOMX_FLAG_FULL_MEM);
120 return randomx_create_vm(fastFlags, NULL, g_dataset);
121 }
122 // Light mode: own VM sharing the cache
123 return randomx_create_vm(g_flags, g_cache, NULL);
124}
125
126
127void RandomXDestroyMinerVM(void* vm)
128{
129 if (vm)
130 randomx_destroy_vm((randomx_vm*)vm);
131}
132
133
134uint256 RandomXHashWithVM(void* vm, const void* pHeader, size_t nSize)
135{
136 uint256 result = 0;
137 if (!vm)
138 return result;
139 unsigned char hash[RANDOMX_HASH_SIZE];
140 randomx_calculate_hash((randomx_vm*)vm, pHeader, nSize, hash);
141 memcpy(&result, hash, RANDOMX_HASH_SIZE);
142 return result;
143}