mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 15:41:44 +02:00
Merge pull request #469 from jeffro256/fcmp++-stage-randomxv2
cryptonote_core: support RandomX V2 and commitments in v17
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Block hashing
|
||||
|
||||
## Background
|
||||
|
||||
In Bitcoin, block IDs and Proof-of-Work (PoW) hashes are calculated the same way, which is why on-chain block IDs always start
|
||||
with many 0s. However, in Monero, block IDs and PoW hashes are calculated using different hash functions and slightly different
|
||||
inputs. This is because the hash functions used for PoW (CryptoNight and RandomX) are much slower to run than other
|
||||
cryptographic hash functions, specifically Keccak256, which Monero uses for block IDs. By contrast, Bitcoin uses SHA-256 for
|
||||
both block IDs and PoW. The reason that CryptoNight and RandomX were chosen for PoW in Monero is to protect against
|
||||
application-specific integrated circuits (ASICs) from dominanting the network hashrate like in Bitcoin. In theory, this
|
||||
would restore the principle of "1 CPU, 1 vote" outlined in the Satoshi whitepaper, and bring greater decentralization to the
|
||||
Monero exosystem. This document aims to describe exactly how block IDs and PoW hashes are calculated in the Monero reference
|
||||
codebase.
|
||||
|
||||
## CryptoNight epoch
|
||||
|
||||
To be reductive, the underlying design of Cryptonight is to 1) fill a 2MB buffer of memory using a memory-hard function, 2)
|
||||
perform over a millon random reads on that buffer to permutate some state, and then 3) do a final hash on the state using
|
||||
a random choice between four independent hash fuctions. There are 4 variants of CryptoNight: v0, v1, v2, and v4. This is the
|
||||
data flow for how block hashing in the CryptoNight epoch (Monero fork versions v1-v11) is performed:
|
||||
|
||||

|
||||
|
||||
## RandomX epoch
|
||||
|
||||
Like, CryptoNight, RandomX also uses a memory hard function to fill a large space of memory called a "cache". However, this
|
||||
space is 256MB, not 2MB. It can be further expanded to 2GB to trade memory usage for compute speed. Unlike CryptoNight's cache,
|
||||
the RandomX cache is computed only once every 2048 blocks, not once per block. Monero uses a "seed" block ID of a previous block
|
||||
in the chain to fill the memory space. And to make ASICs even harder, RandomX uses random instruction execution as well. This
|
||||
is the data flow for how block hashing in the RandomX epoch (Monero fork versions v12-present) is performed:
|
||||
|
||||

|
||||
|
||||
## RandomX, with commitments, epoch
|
||||
|
||||
Because RandomX can be slow to run, especially while building the cache (nearly 1/2 a second on my machine), it inadvertantly
|
||||
can introduce a Denial-of-Service (DoS) vector. For this reason, RandomX hash commitments can be added, so the PoW can be
|
||||
partially verified using only Blake2B, a much lighter hash function. For simplicity's sake, we can also remove the number of
|
||||
transactions in the block from the block hashing blob. This is the data flow for how block hashing works with these changes:
|
||||
|
||||

|
||||
|
||||
The way that the hashes are calculated allows us to do partial PoW verification like so:
|
||||
|
||||

|
||||
|
||||
A node can be given simply the block header, block content hash, and intermediate PoW hash, and verify that some PoW was done
|
||||
using only `randomx_calculate_commitment()` (Blake2B underneath). Passing this partial verification requires PoW to be done using
|
||||
Blake2B up to the relevant difficulty. While doing so is much easier than doing the full RandomX PoW, it still requires
|
||||
significant work. It is very important that we can calculate the block ID from the same information (or a subset thereof)
|
||||
that we calculate PoW from, since each block header contains the previous block ID. Binding the block headers as such makes
|
||||
faking intermediate PoW on chains of blocks exponentially harder the longer the chain is.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
Vendored
+1
-1
Submodule external/randomx updated: 12f2c2ffe2...aaafe71322
@@ -97,13 +97,18 @@ bool tree_branch(const char (*hashes)[HASH_SIZE], size_t count, const char *hash
|
||||
bool tree_branch_hash(const char hash[HASH_SIZE], const char (*branch)[HASH_SIZE], size_t depth, uint32_t path, char root[HASH_SIZE]);
|
||||
bool is_branch_in_tree(const char hash[HASH_SIZE], const char root[HASH_SIZE], const char (*branch)[HASH_SIZE], size_t depth, uint32_t path);
|
||||
|
||||
#define RX_BLOCK_VERSION 12
|
||||
#define RX_VARIANT_1 1
|
||||
#define RX_VARIANT_2 2
|
||||
#define RX_VARIANT_LATEST 0
|
||||
void rx_slow_hash_allocate_state(void);
|
||||
void rx_slow_hash_free_state(void);
|
||||
uint64_t rx_seedheight(const uint64_t height);
|
||||
void rx_seedheights(const uint64_t height, uint64_t *seed_height, uint64_t *next_height);
|
||||
|
||||
void rx_set_main_seedhash(const char *seedhash, size_t max_dataset_init_threads);
|
||||
void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *result_hash);
|
||||
void rx_slow_hash(const char *seedhash, const int variant, const void *data, size_t length, char *result_hash);
|
||||
void rx_commitment(const void *data, size_t length, const void *rx_hash, char *result_commitment);
|
||||
|
||||
void rx_set_miner_thread(uint32_t value, size_t max_dataset_init_threads);
|
||||
uint32_t rx_get_miner_thread(void);
|
||||
|
||||
+83
-32
@@ -66,8 +66,11 @@ static int secondary_seedhash_set = 0;
|
||||
#define THREADV _Thread_local
|
||||
#endif
|
||||
|
||||
static THREADV int main_vm_full_variant = 0;
|
||||
static THREADV randomx_vm *main_vm_full = NULL;
|
||||
static THREADV int main_vm_light_variant = 0;
|
||||
static THREADV randomx_vm *main_vm_light = NULL;
|
||||
static THREADV int secondary_vm_light_variant = 0;
|
||||
static THREADV randomx_vm *secondary_vm_light = NULL;
|
||||
|
||||
static THREADV uint32_t miner_thread = 0;
|
||||
@@ -86,7 +89,7 @@ static void local_abort(const char *msg)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void hash2hex(const char* hash, char* hex) {
|
||||
static void hash2hex(const char hash[HASH_SIZE], char hex[HASH_SIZE * 2 + 1]) {
|
||||
const char* d = "0123456789abcdef";
|
||||
for (int i = 0; i < HASH_SIZE; ++i) {
|
||||
const uint8_t b = hash[i];
|
||||
@@ -116,6 +119,13 @@ static inline int disabled_flags(void) {
|
||||
else {
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
if (flags & RANDOMX_FLAG_V2)
|
||||
{
|
||||
mwarning(RX_LOGCAT,
|
||||
"MONERO_RANDOMX_UMASK would mask RandomX V2, ignoring that bit...");
|
||||
flags &= ~RANDOMX_FLAG_V2;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
@@ -133,6 +143,28 @@ static inline int enabled_flags(void) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
static randomx_flags get_variant_flags(const int variant) {
|
||||
switch (variant)
|
||||
{
|
||||
case RX_VARIANT_1:
|
||||
break;
|
||||
case RX_VARIANT_LATEST:
|
||||
case RX_VARIANT_2:
|
||||
return RANDOMX_FLAG_V2;
|
||||
default:
|
||||
local_abort("Unrecognized RandomX variant");
|
||||
}
|
||||
|
||||
return RANDOMX_FLAG_DEFAULT;
|
||||
}
|
||||
|
||||
static void rx_destroy_vm(randomx_vm** vm) {
|
||||
if (*vm) {
|
||||
randomx_destroy_vm(*vm);
|
||||
*vm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define SEEDHASH_EPOCH_BLOCKS 2048 /* Must be same as BLOCKS_SYNCHRONIZING_MAX_COUNT in cryptonote_config.h */
|
||||
#define SEEDHASH_EPOCH_LAG 64
|
||||
|
||||
@@ -189,7 +221,7 @@ void rx_seedheights(const uint64_t height, uint64_t *seedheight, uint64_t *nexth
|
||||
*nextheight = rx_seedheight(height + get_seedhash_epoch_lag());
|
||||
}
|
||||
|
||||
static void rx_alloc_dataset(randomx_flags flags, randomx_dataset** dataset, int ignore_env)
|
||||
static void rx_alloc_dataset(randomx_dataset** dataset, int ignore_env)
|
||||
{
|
||||
if (*dataset) {
|
||||
return;
|
||||
@@ -213,6 +245,8 @@ static void rx_alloc_dataset(randomx_flags flags, randomx_dataset** dataset, int
|
||||
return;
|
||||
}
|
||||
|
||||
const randomx_flags flags = enabled_flags();
|
||||
|
||||
*dataset = randomx_alloc_dataset((flags | RANDOMX_FLAG_LARGE_PAGES) & ~disabled_flags());
|
||||
if (!*dataset) {
|
||||
alloc_err_msg("Couldn't allocate RandomX dataset using large pages");
|
||||
@@ -223,12 +257,14 @@ static void rx_alloc_dataset(randomx_flags flags, randomx_dataset** dataset, int
|
||||
}
|
||||
}
|
||||
|
||||
static void rx_alloc_cache(randomx_flags flags, randomx_cache** cache)
|
||||
static void rx_alloc_cache(randomx_cache** cache)
|
||||
{
|
||||
if (*cache) {
|
||||
return;
|
||||
}
|
||||
|
||||
const randomx_flags flags = enabled_flags();
|
||||
|
||||
*cache = randomx_alloc_cache((flags | RANDOMX_FLAG_LARGE_PAGES) & ~disabled_flags());
|
||||
if (!*cache) {
|
||||
alloc_err_msg("Couldn't allocate RandomX cache using large pages");
|
||||
@@ -237,51 +273,72 @@ static void rx_alloc_cache(randomx_flags flags, randomx_cache** cache)
|
||||
}
|
||||
}
|
||||
|
||||
static void rx_init_full_vm(randomx_flags flags, randomx_vm** vm)
|
||||
static void rx_init_full_vm(const int variant, randomx_vm** vm, int* vm_variant)
|
||||
{
|
||||
if (*vm || !main_dataset || (disabled_flags() & RANDOMX_FLAG_FULL_MEM)) {
|
||||
if (!main_dataset || (disabled_flags() & RANDOMX_FLAG_FULL_MEM)) {
|
||||
return;
|
||||
}
|
||||
else if (*vm && variant == *vm_variant) {
|
||||
return;
|
||||
}
|
||||
else if (*vm)
|
||||
{
|
||||
// VM is already constructed, but has wrong variant
|
||||
rx_destroy_vm(vm);
|
||||
}
|
||||
|
||||
randomx_flags flags = enabled_flags();
|
||||
if ((flags & RANDOMX_FLAG_JIT) && !miner_thread) {
|
||||
flags |= RANDOMX_FLAG_SECURE;
|
||||
}
|
||||
flags |= RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_FULL_MEM;
|
||||
flags &= ~disabled_flags();
|
||||
flags |= get_variant_flags(variant);
|
||||
|
||||
*vm = randomx_create_vm((flags | RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_FULL_MEM) & ~disabled_flags(), NULL, main_dataset);
|
||||
*vm = randomx_create_vm(flags, NULL, main_dataset);
|
||||
*vm_variant = variant;
|
||||
if (!*vm) {
|
||||
static int shown = 0;
|
||||
if (!shown) {
|
||||
shown = 1;
|
||||
alloc_err_msg("Couldn't allocate RandomX full VM using large pages (will print only once)");
|
||||
}
|
||||
*vm = randomx_create_vm((flags | RANDOMX_FLAG_FULL_MEM) & ~disabled_flags(), NULL, main_dataset);
|
||||
*vm = randomx_create_vm(flags & ~RANDOMX_FLAG_LARGE_PAGES, NULL, main_dataset);
|
||||
if (!*vm) {
|
||||
merror(RX_LOGCAT, "Couldn't allocate RandomX full VM");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rx_init_light_vm(randomx_flags flags, randomx_vm** vm, randomx_cache* cache)
|
||||
static void rx_init_light_vm(const int variant, randomx_vm** vm, int* vm_variant, randomx_cache* cache)
|
||||
{
|
||||
if (*vm) {
|
||||
if (*vm && variant == *vm_variant) {
|
||||
randomx_vm_set_cache(*vm, cache);
|
||||
return;
|
||||
}
|
||||
else if (*vm)
|
||||
{
|
||||
// VM is already constructed, but has wrong variant
|
||||
rx_destroy_vm(vm);
|
||||
}
|
||||
|
||||
randomx_flags flags = enabled_flags();
|
||||
if ((flags & RANDOMX_FLAG_JIT) && !miner_thread) {
|
||||
flags |= RANDOMX_FLAG_SECURE;
|
||||
}
|
||||
flags |= RANDOMX_FLAG_LARGE_PAGES;
|
||||
flags &= ~(disabled_flags() | RANDOMX_FLAG_FULL_MEM);
|
||||
flags |= get_variant_flags(variant);
|
||||
|
||||
flags &= ~RANDOMX_FLAG_FULL_MEM;
|
||||
|
||||
*vm = randomx_create_vm((flags | RANDOMX_FLAG_LARGE_PAGES) & ~disabled_flags(), cache, NULL);
|
||||
*vm = randomx_create_vm(flags, cache, NULL);
|
||||
*vm_variant = variant;
|
||||
if (!*vm) {
|
||||
static int shown = 0;
|
||||
if (!shown) {
|
||||
shown = 1;
|
||||
alloc_err_msg("Couldn't allocate RandomX light VM using large pages (will print only once)");
|
||||
}
|
||||
*vm = randomx_create_vm(flags & ~disabled_flags(), cache, NULL);
|
||||
*vm = randomx_create_vm(flags & ~RANDOMX_FLAG_LARGE_PAGES, cache, NULL);
|
||||
if (!*vm) local_abort("Couldn't allocate RandomX light VM");
|
||||
}
|
||||
}
|
||||
@@ -367,9 +424,8 @@ static CTHR_THREAD_RTYPE rx_set_main_seedhash_thread(void *arg) {
|
||||
hash2hex(main_seedhash, buf);
|
||||
minfo(RX_LOGCAT, "RandomX new main seed hash is %s", buf);
|
||||
|
||||
const randomx_flags flags = enabled_flags() & ~disabled_flags();
|
||||
rx_alloc_dataset(flags, &main_dataset, 0);
|
||||
rx_alloc_cache(flags, &main_cache);
|
||||
rx_alloc_dataset(&main_dataset, 0);
|
||||
rx_alloc_cache(&main_cache);
|
||||
|
||||
randomx_init_cache(main_cache, info->seedhash, HASH_SIZE);
|
||||
minfo(RX_LOGCAT, "RandomX main cache initialized");
|
||||
@@ -405,8 +461,7 @@ void rx_set_main_seedhash(const char *seedhash, size_t max_dataset_init_threads)
|
||||
CTHR_THREAD_CLOSE(t);
|
||||
}
|
||||
|
||||
void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *result_hash) {
|
||||
const randomx_flags flags = enabled_flags() & ~disabled_flags();
|
||||
void rx_slow_hash(const char *seedhash, const int variant, const void *data, size_t length, char *result_hash) {
|
||||
int success = 0;
|
||||
|
||||
// Fast path (seedhash == main_seedhash)
|
||||
@@ -416,7 +471,7 @@ void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *r
|
||||
if (main_dataset && CTHR_RWLOCK_TRYLOCK_READ(main_dataset_lock)) {
|
||||
// Double check that main_seedhash didn't change
|
||||
if (is_main(seedhash)) {
|
||||
rx_init_full_vm(flags, &main_vm_full);
|
||||
rx_init_full_vm(variant, &main_vm_full, &main_vm_full_variant);
|
||||
if (main_vm_full) {
|
||||
randomx_calculate_hash(main_vm_full, data, length, result_hash);
|
||||
success = 1;
|
||||
@@ -427,7 +482,7 @@ void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *r
|
||||
CTHR_RWLOCK_LOCK_READ(main_cache_lock);
|
||||
// Double check that main_seedhash didn't change
|
||||
if (is_main(seedhash)) {
|
||||
rx_init_light_vm(flags, &main_vm_light, main_cache);
|
||||
rx_init_light_vm(variant, &main_vm_light, &main_vm_light_variant, main_cache);
|
||||
randomx_calculate_hash(main_vm_light, data, length, result_hash);
|
||||
success = 1;
|
||||
}
|
||||
@@ -449,7 +504,7 @@ void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *r
|
||||
hash2hex(seedhash, buf);
|
||||
minfo(RX_LOGCAT, "RandomX new secondary seed hash is %s", buf);
|
||||
|
||||
rx_alloc_cache(flags, &secondary_cache);
|
||||
rx_alloc_cache(&secondary_cache);
|
||||
randomx_init_cache(secondary_cache, seedhash, HASH_SIZE);
|
||||
minfo(RX_LOGCAT, "RandomX secondary cache updated");
|
||||
memcpy(secondary_seedhash, seedhash, HASH_SIZE);
|
||||
@@ -460,7 +515,7 @@ void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *r
|
||||
|
||||
CTHR_RWLOCK_LOCK_READ(secondary_cache_lock);
|
||||
if (is_secondary(seedhash)) {
|
||||
rx_init_light_vm(flags, &secondary_vm_light, secondary_cache);
|
||||
rx_init_light_vm(variant, &secondary_vm_light, &secondary_vm_light_variant, secondary_cache);
|
||||
randomx_calculate_hash(secondary_vm_light, data, length, result_hash);
|
||||
success = 1;
|
||||
}
|
||||
@@ -482,11 +537,15 @@ void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *r
|
||||
memcpy(secondary_seedhash, seedhash, HASH_SIZE);
|
||||
secondary_seedhash_set = 1;
|
||||
}
|
||||
rx_init_light_vm(flags, &secondary_vm_light, secondary_cache);
|
||||
rx_init_light_vm(variant, &secondary_vm_light, &secondary_vm_light_variant, secondary_cache);
|
||||
randomx_calculate_hash(secondary_vm_light, data, length, result_hash);
|
||||
CTHR_RWLOCK_UNLOCK_WRITE(secondary_cache_lock);
|
||||
}
|
||||
|
||||
void rx_commitment(const void *data, size_t length, const void *rx_hash, char *result_commitment) {
|
||||
randomx_calculate_commitment(data, length, rx_hash, result_commitment);
|
||||
}
|
||||
|
||||
void rx_set_miner_thread(uint32_t value, size_t max_dataset_init_threads) {
|
||||
miner_thread = value;
|
||||
|
||||
@@ -497,8 +556,7 @@ void rx_set_miner_thread(uint32_t value, size_t max_dataset_init_threads) {
|
||||
return;
|
||||
}
|
||||
|
||||
const randomx_flags flags = enabled_flags() & ~disabled_flags();
|
||||
rx_alloc_dataset(flags, &main_dataset, 1);
|
||||
rx_alloc_dataset(&main_dataset, 1);
|
||||
rx_init_dataset(max_dataset_init_threads);
|
||||
|
||||
CTHR_RWLOCK_UNLOCK_WRITE(main_dataset_lock);
|
||||
@@ -510,13 +568,6 @@ uint32_t rx_get_miner_thread(void) {
|
||||
|
||||
void rx_slow_hash_allocate_state(void) {}
|
||||
|
||||
static void rx_destroy_vm(randomx_vm** vm) {
|
||||
if (*vm) {
|
||||
randomx_destroy_vm(*vm);
|
||||
*vm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void rx_slow_hash_free_state(void) {
|
||||
rx_destroy_vm(&main_vm_full);
|
||||
rx_destroy_vm(&main_vm_light);
|
||||
|
||||
@@ -2019,10 +2019,16 @@ namespace cryptonote
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
int get_randomx_variant_for_hf_version(const std::uint8_t hf_version)
|
||||
{
|
||||
return (hf_version >= HF_VERSION_RANDOMX_V2) ? RX_VARIANT_2 : RX_VARIANT_1;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_block_longhash(const blobdata_ref block_hashing_blob,
|
||||
const uint64_t height,
|
||||
const uint8_t major_version,
|
||||
const crypto::hash &seed_hash)
|
||||
const crypto::hash &seed_hash,
|
||||
crypto::hash &intermediate_hash_out)
|
||||
{
|
||||
crypto::hash res;
|
||||
|
||||
@@ -2031,7 +2037,12 @@ namespace cryptonote
|
||||
|
||||
if (major_version >= RX_BLOCK_VERSION) // RandomX
|
||||
{
|
||||
crypto::rx_slow_hash(seed_hash.data, block_hashing_blob.data(), block_hashing_blob.size(), res.data);
|
||||
const int rx_variant = get_randomx_variant_for_hf_version(major_version);
|
||||
crypto::rx_slow_hash(seed_hash.data, rx_variant,
|
||||
block_hashing_blob.data(), block_hashing_blob.size(), res.data);
|
||||
intermediate_hash_out = res;
|
||||
if (major_version >= HF_VERSION_POW_COMMITMENT)
|
||||
crypto::rx_commitment(block_hashing_blob.data(), block_hashing_blob.size(), res.data, res.data);
|
||||
}
|
||||
else // CryptoNight
|
||||
{
|
||||
@@ -2044,6 +2055,15 @@ namespace cryptonote
|
||||
return res;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_block_longhash(const blobdata_ref block_hashing_blob,
|
||||
const uint64_t height,
|
||||
const uint8_t major_version,
|
||||
const crypto::hash &seed_hash)
|
||||
{
|
||||
crypto::hash intermediate_hash;
|
||||
return get_block_longhash(block_hashing_blob, height, major_version, seed_hash, intermediate_hash);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool is_valid_decomposed_amount(uint64_t amount)
|
||||
{
|
||||
if (0 == amount)
|
||||
|
||||
@@ -303,6 +303,12 @@ namespace cryptonote
|
||||
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h);
|
||||
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
|
||||
crypto::hash get_tx_tree_hash(const block& b);
|
||||
int get_randomx_variant_for_hf_version(const std::uint8_t hf_version);
|
||||
crypto::hash get_block_longhash(const blobdata_ref block_hashing_blob,
|
||||
const uint64_t height,
|
||||
const uint8_t major_version,
|
||||
const crypto::hash &seed_hash,
|
||||
crypto::hash &intermediate_hash_out);
|
||||
crypto::hash get_block_longhash(const blobdata_ref block_hashing_blob,
|
||||
const uint64_t height,
|
||||
const uint8_t major_version,
|
||||
|
||||
@@ -208,6 +208,8 @@
|
||||
#define HF_VERSION_REJECT_UNMIXABLE_V1 17
|
||||
#define HF_VERSION_REJECT_MANY_MINER_OUTPUTS 17
|
||||
#define HF_VERSION_2026_SCALING 17
|
||||
#define HF_VERSION_POW_COMMITMENT 17
|
||||
#define HF_VERSION_RANDOMX_V2 17
|
||||
#define MAX_HF_VERSION 18
|
||||
|
||||
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace cryptonote
|
||||
m_mempool(m_bap.tx_pool),
|
||||
m_blockchain_storage(m_bap.blockchain),
|
||||
m_miner(this, [this](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&m_blockchain_storage, b, hash, height, seed_hash, threads);
|
||||
return cryptonote::get_block_longhash(&m_blockchain_storage, b, hash, height, seed_hash);
|
||||
}),
|
||||
m_starter_message_showed(false),
|
||||
m_target_blockchain_height(0),
|
||||
|
||||
@@ -737,7 +737,7 @@ namespace cryptonote
|
||||
bl.timestamp = 0;
|
||||
bl.nonce = nonce;
|
||||
miner::find_nonce_for_given_block([](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(NULL, b, hash, height, seed_hash, threads);
|
||||
return cryptonote::get_block_longhash(NULL, b, hash, height, seed_hash);
|
||||
}, bl, 1, 0, NULL);
|
||||
bl.invalidate_hashes();
|
||||
return true;
|
||||
@@ -746,10 +746,13 @@ namespace cryptonote
|
||||
void get_altblock_longhash(const block& b, crypto::hash& res, const crypto::hash& seed_hash)
|
||||
{
|
||||
blobdata bd = get_block_hashing_blob(b);
|
||||
rx_slow_hash(seed_hash.data, bd.data(), bd.size(), res.data);
|
||||
const int rx_variant = get_randomx_variant_for_hf_version(b.major_version);
|
||||
crypto::rx_slow_hash(seed_hash.data, rx_variant, bd.data(), bd.size(), res.data);
|
||||
if (b.major_version >= HF_VERSION_POW_COMMITMENT)
|
||||
crypto::rx_commitment(bd.data(), bd.size(), res.data, res.data);
|
||||
}
|
||||
|
||||
bool get_block_longhash(const Blockchain *pbc, const blobdata& bd, crypto::hash& res, const uint64_t height, const int major_version, const crypto::hash *seed_hash, const int miners)
|
||||
bool get_block_longhash(const Blockchain *pbc, const blobdata& bd, crypto::hash& res, const uint64_t height, const int major_version, const crypto::hash *seed_hash, crypto::hash *intermediate_hash_out)
|
||||
{
|
||||
crypto::hash seed_hash_ = crypto::null_hash;
|
||||
if (pbc != NULL && major_version >= RX_BLOCK_VERSION)
|
||||
@@ -757,20 +760,23 @@ namespace cryptonote
|
||||
const uint64_t seed_height = rx_seedheight(height);
|
||||
seed_hash_ = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
|
||||
}
|
||||
res = get_block_longhash(bd, height, major_version, seed_hash_);
|
||||
crypto::hash intermediate_hash;
|
||||
res = get_block_longhash(bd, height, major_version, seed_hash_, intermediate_hash);
|
||||
if (intermediate_hash_out)
|
||||
*intermediate_hash_out = intermediate_hash;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash, const int miners)
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash, crypto::hash *intermediate_hash_out)
|
||||
{
|
||||
blobdata bd = get_block_hashing_blob(b);
|
||||
return get_block_longhash(pbc, bd, res, height, b.major_version, seed_hash, miners);
|
||||
return get_block_longhash(pbc, bd, res, height, b.major_version, seed_hash, intermediate_hash_out);
|
||||
}
|
||||
|
||||
crypto::hash get_block_longhash(const Blockchain *pbc, const block& b, const uint64_t height, const crypto::hash *seed_hash, const int miners)
|
||||
crypto::hash get_block_longhash(const Blockchain *pbc, const block& b, const uint64_t height, const crypto::hash *seed_hash, crypto::hash *intermediate_hash_out)
|
||||
{
|
||||
crypto::hash p = crypto::null_hash;
|
||||
get_block_longhash(pbc, b, p, height, seed_hash, miners);
|
||||
get_block_longhash(pbc, b, p, height, seed_hash, intermediate_hash_out);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,9 +162,9 @@ namespace cryptonote
|
||||
);
|
||||
|
||||
class Blockchain;
|
||||
bool get_block_longhash(const Blockchain *pb, const blobdata& bd, crypto::hash& res, const uint64_t height, const int major_version, const crypto::hash *seed_hash, const int miners = 0);
|
||||
bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash = nullptr, const int miners = 0);
|
||||
crypto::hash get_block_longhash(const Blockchain *pb, const block& b, const uint64_t height, const crypto::hash *seed_hash = nullptr, const int miners = 0);
|
||||
bool get_block_longhash(const Blockchain *pb, const blobdata& bd, crypto::hash& res, const uint64_t height, const int major_version, const crypto::hash *seed_hash, crypto::hash *intermediate_hash_out = nullptr);
|
||||
bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash = nullptr, crypto::hash *intermediate_hash_out = nullptr);
|
||||
crypto::hash get_block_longhash(const Blockchain *pb, const block& b, const uint64_t height, const crypto::hash *seed_hash = nullptr, crypto::hash *intermediate_hash_out = nullptr);
|
||||
void get_altblock_longhash(const block& b, crypto::hash& res, const crypto::hash& seed_hash);
|
||||
|
||||
}
|
||||
|
||||
@@ -2164,7 +2164,7 @@ namespace cryptonote
|
||||
return false;
|
||||
}
|
||||
miner::find_nonce_for_given_block([this](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&(m_core.get_blockchain_storage()), b, hash, height, seed_hash, threads);
|
||||
return cryptonote::get_block_longhash(&(m_core.get_blockchain_storage()), b, hash, height, seed_hash);
|
||||
}, b, template_res.difficulty, template_res.height, &seed_hash);
|
||||
|
||||
submit_req.front() = string_tools::buff_to_hex_nodelimer(block_to_blob(b));
|
||||
|
||||
@@ -411,7 +411,7 @@ void test_generator::fill_nonce(cryptonote::block& blk, const difficulty_type& d
|
||||
|
||||
blk.nonce = 0;
|
||||
while (!miner::find_nonce_for_given_block([blockchain](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(blockchain, b, hash, height, seed_hash, threads);
|
||||
return cryptonote::get_block_longhash(blockchain, b, hash, height, seed_hash);
|
||||
}, blk, diffic, height, NULL)) {
|
||||
blk.timestamp++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user