From 24dc8252a386a9528711c1c2d68988aa60ef6f1b Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 8 Nov 2022 09:29:05 -0500 Subject: [PATCH 01/13] Add scripts to research randomx difficulty problems --- src/testdragonx-cli | 13 +++++++++++++ src/testdragonxd | 17 +++++++++++++++++ src/testequihash-cli | 13 +++++++++++++ src/testequihashd | 18 ++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100755 src/testdragonx-cli create mode 100755 src/testdragonxd create mode 100755 src/testequihash-cli create mode 100755 src/testequihashd diff --git a/src/testdragonx-cli b/src/testdragonx-cli new file mode 100755 index 000000000..e1f94b2c7 --- /dev/null +++ b/src/testdragonx-cli @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Copyright 2016-2022 The Hush Developers +# Copyright 2022 The DragonX Developers +# Released under the GPLv3 + +# set working directory to the location of this script +# readlink -f does not always exist +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $DIR +DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )" +cd $DIR + +./hush-cli -ac_name=TESTDRAGONX $@ diff --git a/src/testdragonxd b/src/testdragonxd new file mode 100755 index 000000000..d769509d5 --- /dev/null +++ b/src/testdragonxd @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# Copyright 2016-2022 The Hush Developers +# Copyright 2022 The DragonX Developers +# Released under the GPLv3 + +# set working directory to the location of this script +# readlink -f does not always exist +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $DIR +DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )" +cd $DIR + +BLOCKTIME=18 +SUPPLY=0 + +# Remember Remember the 5th November for freedom of speech is not free!! +./hush-smart-chain -ac_name=TESTDRAGONX -ac_algo=randomx -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=$BLOCKTIME -ac_private=1 -ac_supply=$SUPPLY -gen=1 -genproclimit=1 -debug=randomx $@ diff --git a/src/testequihash-cli b/src/testequihash-cli new file mode 100755 index 000000000..abe243979 --- /dev/null +++ b/src/testequihash-cli @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Copyright 2016-2022 The Hush Developers +# Copyright 2022 The DragonX Developers +# Released under the GPLv3 + +# set working directory to the location of this script +# readlink -f does not always exist +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $DIR +DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )" +cd $DIR + +./hush-cli -ac_name=TESTEQUIHASH $@ diff --git a/src/testequihashd b/src/testequihashd new file mode 100755 index 000000000..4e7a0c64c --- /dev/null +++ b/src/testequihashd @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Copyright 2016-2022 The Hush Developers +# Copyright 2022 The DragonX Developers +# Released under the GPLv3 + +# set working directory to the location of this script +# readlink -f does not always exist +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $DIR +DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )" +cd $DIR + +BLOCKTIME=18 +SUPPLY=0 + +# same as TESTDRAGONX except equihash and different ac_name +# and debug=pow which is the equivalent of debug=randomx for equihash mining +./hush-smart-chain -ac_name=TESTEQUIHASH -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=$BLOCKTIME -ac_private=1 -ac_supply=$SUPPLY -gen=1 -genproclimit=1 -testnode=1 -debug=pow $@ From c81b49c96c780455125be726098384858048dbfa Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 8 Nov 2022 09:55:46 -0500 Subject: [PATCH 02/13] fix params for testcoins --- src/testdragonxd | 2 +- src/testequihashd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/testdragonxd b/src/testdragonxd index d769509d5..6a1c9e86f 100755 --- a/src/testdragonxd +++ b/src/testdragonxd @@ -14,4 +14,4 @@ BLOCKTIME=18 SUPPLY=0 # Remember Remember the 5th November for freedom of speech is not free!! -./hush-smart-chain -ac_name=TESTDRAGONX -ac_algo=randomx -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=$BLOCKTIME -ac_private=1 -ac_supply=$SUPPLY -gen=1 -genproclimit=1 -debug=randomx $@ +./hush-smart-chain -ac_name=TESTDRAGONX -ac_algo=randomx -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=$BLOCKTIME -ac_private=1 -ac_supply=$SUPPLY -debug=randomx $@ diff --git a/src/testequihashd b/src/testequihashd index 4e7a0c64c..9571566a2 100755 --- a/src/testequihashd +++ b/src/testequihashd @@ -15,4 +15,4 @@ SUPPLY=0 # same as TESTDRAGONX except equihash and different ac_name # and debug=pow which is the equivalent of debug=randomx for equihash mining -./hush-smart-chain -ac_name=TESTEQUIHASH -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=$BLOCKTIME -ac_private=1 -ac_supply=$SUPPLY -gen=1 -genproclimit=1 -testnode=1 -debug=pow $@ +./hush-smart-chain -ac_name=TESTEQUIHASH -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=$BLOCKTIME -ac_private=1 -ac_supply=$SUPPLY -debug=pow $@ From b94ec8030729011ad408d4846bb6f73df2eefcce Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 10 Nov 2022 22:38:04 -0500 Subject: [PATCH 03/13] Use RANDOMX_FLAG_FULL_MEM --- src/miner.cpp | 71 +++++++++++++++++++++++++++++++------------ src/wallet/wallet.cpp | 2 +- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 92acea2d9..f39b94979 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1065,6 +1065,23 @@ void static RandomXMiner() cancelSolver = true; } ); + randomx_flags flags = randomx_get_flags(); + // flags |= RANDOMX_FLAG_LARGE_PAGES; + flags |= RANDOMX_FLAG_FULL_MEM; + //flags |= RANDOMX_FLAG_JIT; + randomx_cache *randomxCache = randomx_alloc_cache(flags); + if (randomxCache == NULL) { + LogPrintf("RandomX cache is null, something is wrong, cannot mine!\n"); + return; + } + rxdebug("%s: created randomx flags + cache\n"); + + randomx_dataset *randomxDataset = randomx_alloc_dataset(flags); + rxdebug("%s: created dataset\n"); + if( randomxDataset == nullptr) { + LogPrintf("%s: allocating randomx dataset failed!\n", __func__); + return; + } miningTimer.start(); try { @@ -1181,8 +1198,8 @@ void static RandomXMiner() HASHTarget = arith_uint256().SetCompact(savebits); roundrobin_delay = ROUNDROBIN_DELAY; Mining_start = 0; - gotinvalid = 0; + while (true) { if ( gotinvalid != 0 ) { @@ -1199,7 +1216,7 @@ void static RandomXMiner() char randomxHash[RANDOMX_HASH_SIZE]; //fprintf(stderr,"RandomXMiner: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific - // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^128 bits) of entropy + // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy // since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT); @@ -1211,14 +1228,6 @@ void static RandomXMiner() // fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput); rxdebug("%s: randomxKey=%s randomxInput=%s\n", randomxKey, HexStr(randomxInput).c_str()); - randomx_flags flags = randomx_get_flags(); - randomx_cache *randomxCache = randomx_alloc_cache(flags); - if (randomxCache == NULL) { - LogPrintf("RandomX cache is null, something is wrong, cannot mine!\n"); - return; - } - // fprintf(stderr,"RandomXMiner: created randomx flags + cache\n"); - // With the defaults of 1024 and 64 // the key block will change every ~21.3 hours with a 75s block time // and every ~17 hours with the default 60s block time for HSCs @@ -1240,20 +1249,31 @@ void static RandomXMiner() randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey); rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str()); + } - randomx_vm *myVM = randomx_create_vm(flags, randomxCache, NULL); - if(myVM == NULL) { - LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n"); - return; - } + //TODO: this is hardcoded to use 2 threads instead of the number of mining threads + //std::thread t1(&randomx_init_dataset, randomxDataset, randomxCache, 0, datasetItemCount / 2); + //std::thread t2(&randomx_init_dataset, randomxDataset, randomxCache, datasetItemCount / 2, datasetItemCount - datasetItemCount / 2); + //t1.join(); + //t2.join(); + auto datasetItemCount = randomx_dataset_item_count(); + rxdebug("%s: dataset items=%lu\n", datasetItemCount); + + randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount); + rxdebug("%s: dataset initialized\n"); + // randomx_release_cache(randomxCache); + // rxdebug("%s: cache released\n"); + + randomx_vm *myVM = randomx_create_vm(flags, nullptr, randomxDataset); + if(myVM == NULL) { + LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n"); + return; + } + randomx_calculate_hash(myVM, &randomxInput, sizeof randomxInput, randomxHash); - // rxdebug("calculated randomx hash\n"); - - randomx_destroy_vm(myVM); - // fprintf(stderr,"RandomXMiner: destroyed VM\n"); - randomx_release_cache(randomxCache); + rxdebug("%s: calculated randomx hash\n"); rxdebug("%s: randomxHash="); if (fRandomXDebug) { @@ -1263,6 +1283,9 @@ void static RandomXMiner() printf("\n"); } + randomx_destroy_vm(myVM); + rxdebug("%s: destroyed VM\n"); + // Use randomx hash to build a valid block std::function)> validBlock = @@ -1372,6 +1395,8 @@ void static RandomXMiner() pblock->nBits = savebits; } } + + } catch (const boost::thread_interrupted&) { miningTimer.stop(); c.disconnect(); @@ -1383,6 +1408,11 @@ void static RandomXMiner() fprintf(stderr,"RandomXMiner: runtime error: %s\n", e.what()); return; } + + randomx_release_dataset(randomxDataset); + rxdebug("%s: released dataset\n"); + randomx_release_cache(randomxCache); + rxdebug("%s: released cache\n"); miningTimer.stop(); c.disconnect(); } @@ -1859,6 +1889,7 @@ void static BitcoinMiner() LogPrintf("HushMiner runtime error: %s\n", e.what()); return; } + miningTimer.stop(); c.disconnect(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bc2d75752..001c42718 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2771,7 +2771,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) // our wallet birthday (as adjusted for block time variability) while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200))) { pindex = chainActive.Next(pindex); - pwalletMain->rescanHeight = pindex->GetHeight(); + pwalletMain->rescanHeight = pindex ? pindex->GetHeight() : 0; } ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup From c108db8f3c37cea6b0ec6a458863e5cf70d7f6d8 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 11 Nov 2022 06:42:51 -0500 Subject: [PATCH 04/13] Speed up randomx hashing by ~60X per core These code changes move various randomx setup code out of the inner mining loop, which significantly increases hashrate. Currently seeing ~60 hashes/second/core on a Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz. This code may have memory leaks, it does not destroy the randomx VM since it was causing coredumps. It also seems to use more memory, I am only able to mine on 2 cores with 16GB of RAM. Using more cores runs out of memory. --- src/miner.cpp | 108 +++++++++++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index f39b94979..1ff987e9b 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1131,6 +1131,55 @@ void static RandomXMiner() { Mining_height = pindexPrev->GetHeight()+1; Mining_start = (uint32_t)time(NULL); + } + char randomxHash[RANDOMX_HASH_SIZE]; + rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); + char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific + // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy + // since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long + snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT); + + // With the defaults of 1024 and 64 + // the key block will change every ~21.3 hours with a 75s block time + // and every ~17 hours with the default 60s block time for HSCs + int randomxInterval = GetArg("-ac_randomx_interval",1024); + // This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs + int randomxBlockLag = GetArg("-ac_randomx_lag", 64); + + // fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag); + rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height); + // Use the initial key at the start of the chain, until the first key block + if( (Mining_height) < randomxInterval + randomxBlockLag) { + randomx_init_cache(randomxCache, &randomxKey, sizeof randomxKey); + rxdebug("%s: initialized cache with initial key\n"); + } else { + rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval); + // At heights between intervals, we use the same block key and wait randomxBlockLag blocks until changing + int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval; + uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash(); + + randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey); + rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str()); + + } + + auto datasetItemCount = randomx_dataset_item_count(); + rxdebug("%s: dataset items=%lu\n", datasetItemCount); + //TODO: this is hardcoded to use 2 threads instead of the number of mining threads + //std::thread t1(&randomx_init_dataset, randomxDataset, randomxCache, 0, datasetItemCount / 2); + //std::thread t2(&randomx_init_dataset, randomxDataset, randomxCache, datasetItemCount / 2, datasetItemCount - datasetItemCount / 2); + //t1.join(); + //t2.join(); + + randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount); + rxdebug("%s: dataset initialized\n"); + // randomx_release_cache(randomxCache); + // rxdebug("%s: cache released\n"); + + randomx_vm *myVM = randomx_create_vm(flags, nullptr, randomxDataset); + if(myVM == NULL) { + LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n"); + return; } //fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start); #ifdef ENABLE_WALLET @@ -1185,6 +1234,7 @@ void static RandomXMiner() } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",SMART_CHAIN_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT); } } + rxdebug("%s: incrementing extra nonce\n"); IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); // fprintf(stderr,"RandomXMiner: %u transactions in block\n",(int32_t)pblock->vtx.size()); LogPrintf("Running HushRandomXMiner with %u transactions in block (%u bytes)\n",pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION)); @@ -1213,13 +1263,6 @@ void static RandomXMiner() arith_uint256 hashTarget; hashTarget = HASHTarget; - char randomxHash[RANDOMX_HASH_SIZE]; - //fprintf(stderr,"RandomXMiner: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); - char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific - // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy - // since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long - snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT); - CDataStream randomxInput(SER_NETWORK, PROTOCOL_VERSION); // Use the current block as randomx input randomxInput << pblocktemplate->block; @@ -1228,50 +1271,7 @@ void static RandomXMiner() // fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput); rxdebug("%s: randomxKey=%s randomxInput=%s\n", randomxKey, HexStr(randomxInput).c_str()); - // With the defaults of 1024 and 64 - // the key block will change every ~21.3 hours with a 75s block time - // and every ~17 hours with the default 60s block time for HSCs - int randomxInterval = GetArg("-ac_randomx_interval",1024); - // This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs - int randomxBlockLag = GetArg("-ac_randomx_lag", 64); - - // fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag); - rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height); - // Use the initial key at the start of the chain, until the first key block - if( (Mining_height) < randomxInterval + randomxBlockLag) { - randomx_init_cache(randomxCache, &randomxKey, sizeof randomxKey); - rxdebug("%s: initialized cache with initial key\n"); - } else { - rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval); - // At heights between intervals, we use the same block key and wait randomxBlockLag blocks until changing - int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval; - uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash(); - - randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey); - rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str()); - - } - - //TODO: this is hardcoded to use 2 threads instead of the number of mining threads - //std::thread t1(&randomx_init_dataset, randomxDataset, randomxCache, 0, datasetItemCount / 2); - //std::thread t2(&randomx_init_dataset, randomxDataset, randomxCache, datasetItemCount / 2, datasetItemCount - datasetItemCount / 2); - //t1.join(); - //t2.join(); - auto datasetItemCount = randomx_dataset_item_count(); - rxdebug("%s: dataset items=%lu\n", datasetItemCount); - - randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount); - rxdebug("%s: dataset initialized\n"); - // randomx_release_cache(randomxCache); - // rxdebug("%s: cache released\n"); - - randomx_vm *myVM = randomx_create_vm(flags, nullptr, randomxDataset); - if(myVM == NULL) { - LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n"); - return; - } - - + rxdebug("%s: calculating randomx hash\n"); randomx_calculate_hash(myVM, &randomxInput, sizeof randomxInput, randomxHash); rxdebug("%s: calculated randomx hash\n"); @@ -1283,11 +1283,11 @@ void static RandomXMiner() printf("\n"); } - randomx_destroy_vm(myVM); - rxdebug("%s: destroyed VM\n"); + + //randomx_destroy_vm(myVM); + //rxdebug("%s: destroyed VM\n"); // Use randomx hash to build a valid block - std::function)> validBlock = #ifdef ENABLE_WALLET [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams] From 81f0c7755e6d0958e9c68a1579e499c49cbf24c0 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 12 Nov 2022 09:22:10 -0500 Subject: [PATCH 05/13] Code to test exact cause of the 'up only' diff bug --- src/pow.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pow.cpp b/src/pow.cpp index 753378ba9..31c9eafcf 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -526,7 +526,11 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, // Limit adjustment step and use medians to prevent time-warp attacks int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime; LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan); - int64_t AWT = AveragingWindowTimespan(height) ; + + //NOTE: this will break HUSH+DRAGONX mainnet! For testing only. + int64_t AWT = params.AveragingWindowTimespan(); + //int64_t AWT = AveragingWindowTimespan(height) ; + nActualTimespan = AWT + (nActualTimespan - AWT)/4; LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan); From 3dbe8d3c6bd730982f1e1aaece856ae00f1adfd9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Nov 2022 13:43:10 -0500 Subject: [PATCH 06/13] indentation --- src/miner.cpp | 53 ++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 1ff987e9b..97f093f1e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1132,36 +1132,37 @@ void static RandomXMiner() Mining_height = pindexPrev->GetHeight()+1; Mining_start = (uint32_t)time(NULL); } - char randomxHash[RANDOMX_HASH_SIZE]; - rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); - char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific - // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy - // since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long - snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT); - // With the defaults of 1024 and 64 - // the key block will change every ~21.3 hours with a 75s block time - // and every ~17 hours with the default 60s block time for HSCs - int randomxInterval = GetArg("-ac_randomx_interval",1024); - // This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs - int randomxBlockLag = GetArg("-ac_randomx_lag", 64); + char randomxHash[RANDOMX_HASH_SIZE]; + rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); + char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific + // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy + // since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long + snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT); - // fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag); - rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height); - // Use the initial key at the start of the chain, until the first key block - if( (Mining_height) < randomxInterval + randomxBlockLag) { - randomx_init_cache(randomxCache, &randomxKey, sizeof randomxKey); - rxdebug("%s: initialized cache with initial key\n"); - } else { - rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval); - // At heights between intervals, we use the same block key and wait randomxBlockLag blocks until changing - int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval; - uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash(); + // With the defaults of 1024 and 64 + // the key block will change every ~21.3 hours with a 75s block time + // and every ~17 hours with the default 60s block time for HSCs + int randomxInterval = GetArg("-ac_randomx_interval",1024); + // This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs + int randomxBlockLag = GetArg("-ac_randomx_lag", 64); - randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey); - rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str()); + // fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag); + rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height); + // Use the initial key at the start of the chain, until the first key block + if( (Mining_height) < randomxInterval + randomxBlockLag) { + randomx_init_cache(randomxCache, &randomxKey, sizeof randomxKey); + rxdebug("%s: initialized cache with initial key\n"); + } else { + rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval); + // At heights between intervals, we use the same block key and wait randomxBlockLag blocks until changing + int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval; + uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash(); - } + randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey); + rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str()); + + } auto datasetItemCount = randomx_dataset_item_count(); rxdebug("%s: dataset items=%lu\n", datasetItemCount); From d3b948005c8f68ca7efa7a89b26d1c5b877e0471 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Nov 2022 13:44:47 -0500 Subject: [PATCH 07/13] indentation --- src/miner.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 97f093f1e..1b030ea18 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1065,23 +1065,24 @@ void static RandomXMiner() cancelSolver = true; } ); - randomx_flags flags = randomx_get_flags(); - // flags |= RANDOMX_FLAG_LARGE_PAGES; - flags |= RANDOMX_FLAG_FULL_MEM; - //flags |= RANDOMX_FLAG_JIT; - randomx_cache *randomxCache = randomx_alloc_cache(flags); - if (randomxCache == NULL) { - LogPrintf("RandomX cache is null, something is wrong, cannot mine!\n"); - return; - } - rxdebug("%s: created randomx flags + cache\n"); + randomx_flags flags = randomx_get_flags(); + // flags |= RANDOMX_FLAG_LARGE_PAGES; + flags |= RANDOMX_FLAG_FULL_MEM; + //flags |= RANDOMX_FLAG_JIT; + randomx_cache *randomxCache = randomx_alloc_cache(flags); + if (randomxCache == NULL) { + LogPrintf("RandomX cache is null, something is wrong, cannot mine!\n"); + return; + } + rxdebug("%s: created randomx flags + cache\n"); + randomx_dataset *randomxDataset = randomx_alloc_dataset(flags); + rxdebug("%s: created dataset\n"); + + if( randomxDataset == nullptr) { + LogPrintf("%s: allocating randomx dataset failed!\n", __func__); + return; + } - randomx_dataset *randomxDataset = randomx_alloc_dataset(flags); - rxdebug("%s: created dataset\n"); - if( randomxDataset == nullptr) { - LogPrintf("%s: allocating randomx dataset failed!\n", __func__); - return; - } miningTimer.start(); try { From c55d1cbc5f484e95f5e0f573e43aa4ce93dd795f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Nov 2022 14:02:02 -0500 Subject: [PATCH 08/13] Destroy randomx VM when we are done with it --- src/miner.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 1b030ea18..c1f6f73b6 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1066,6 +1066,7 @@ void static RandomXMiner() } ); randomx_flags flags = randomx_get_flags(); + // TODO: attempt to use large pages and fall back to no large pages // flags |= RANDOMX_FLAG_LARGE_PAGES; flags |= RANDOMX_FLAG_FULL_MEM; //flags |= RANDOMX_FLAG_JIT; @@ -1175,8 +1176,6 @@ void static RandomXMiner() randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount); rxdebug("%s: dataset initialized\n"); - // randomx_release_cache(randomxCache); - // rxdebug("%s: cache released\n"); randomx_vm *myVM = randomx_create_vm(flags, nullptr, randomxDataset); if(myVM == NULL) { @@ -1286,9 +1285,6 @@ void static RandomXMiner() printf("\n"); } - //randomx_destroy_vm(myVM); - //rxdebug("%s: destroyed VM\n"); - // Use randomx hash to build a valid block std::function)> validBlock = #ifdef ENABLE_WALLET @@ -1396,6 +1392,11 @@ void static RandomXMiner() pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); pblock->nBits = savebits; } + + rxdebug("%s: going to destroy rx VM\n"); + randomx_destroy_vm(myVM); + rxdebug("%s: destroyed VM\n"); + } From 1a4e8d4acfba44d4485dc68475a453e1b1ef6eea Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Nov 2022 14:11:55 -0500 Subject: [PATCH 09/13] Initialize randomx dataset with 2 threads --- src/miner.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index c1f6f73b6..a222e4f16 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1168,13 +1168,15 @@ void static RandomXMiner() auto datasetItemCount = randomx_dataset_item_count(); rxdebug("%s: dataset items=%lu\n", datasetItemCount); - //TODO: this is hardcoded to use 2 threads instead of the number of mining threads - //std::thread t1(&randomx_init_dataset, randomxDataset, randomxCache, 0, datasetItemCount / 2); - //std::thread t2(&randomx_init_dataset, randomxDataset, randomxCache, datasetItemCount / 2, datasetItemCount - datasetItemCount / 2); - //t1.join(); - //t2.join(); - randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount); + //TODO: this is hardcoded to use 2 threads instead of the number of mining threads + rxdebug("%s: initializing dataset with 2 threads\n"); + std::thread t1(&randomx_init_dataset, randomxDataset, randomxCache, 0, datasetItemCount / 2); + std::thread t2(&randomx_init_dataset, randomxDataset, randomxCache, datasetItemCount / 2, datasetItemCount - datasetItemCount / 2); + t1.join(); + t2.join(); + + // randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount); rxdebug("%s: dataset initialized\n"); randomx_vm *myVM = randomx_create_vm(flags, nullptr, randomxDataset); From c8b2163c1c9df4aa69815847d708d7445e405ad4 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Nov 2022 14:21:45 -0500 Subject: [PATCH 10/13] Optimize inner mining loop --- src/miner.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index a222e4f16..8288ebfc4 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1079,6 +1079,9 @@ void static RandomXMiner() randomx_dataset *randomxDataset = randomx_alloc_dataset(flags); rxdebug("%s: created dataset\n"); + auto datasetItemCount = randomx_dataset_item_count(); + rxdebug("%s: dataset items=%lu\n", datasetItemCount); + if( randomxDataset == nullptr) { LogPrintf("%s: allocating randomx dataset failed!\n", __func__); return; @@ -1166,9 +1169,6 @@ void static RandomXMiner() } - auto datasetItemCount = randomx_dataset_item_count(); - rxdebug("%s: dataset items=%lu\n", datasetItemCount); - //TODO: this is hardcoded to use 2 threads instead of the number of mining threads rxdebug("%s: initializing dataset with 2 threads\n"); std::thread t1(&randomx_init_dataset, randomxDataset, randomxCache, 0, datasetItemCount / 2); From 665f89513417c0ab2277b205c25f560bbcde0a5a Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Nov 2022 14:40:10 -0500 Subject: [PATCH 11/13] Optimize inner mining loop --- src/miner.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 8288ebfc4..bdf10ec56 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1065,6 +1065,8 @@ void static RandomXMiner() cancelSolver = true; } ); + miningTimer.start(); + randomx_flags flags = randomx_get_flags(); // TODO: attempt to use large pages and fall back to no large pages // flags |= RANDOMX_FLAG_LARGE_PAGES; @@ -1087,7 +1089,20 @@ void static RandomXMiner() return; } - miningTimer.start(); + + char randomxHash[RANDOMX_HASH_SIZE]; + rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); + char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific + // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy + // since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long + snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT); + + // With the defaults of 1024 and 64 + // the key block will change every ~21.3 hours with a 75s block time + // and every ~17 hours with the default 60s block time for HSCs + int randomxInterval = GetArg("-ac_randomx_interval",1024); + // This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs + int randomxBlockLag = GetArg("-ac_randomx_lag", 64); try { // fprintf(stderr,"RandomXMiner: mining %s with randomx\n",SMART_CHAIN_SYMBOL); @@ -1138,19 +1153,6 @@ void static RandomXMiner() Mining_start = (uint32_t)time(NULL); } - char randomxHash[RANDOMX_HASH_SIZE]; - rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); - char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific - // initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy - // since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long - snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT); - - // With the defaults of 1024 and 64 - // the key block will change every ~21.3 hours with a 75s block time - // and every ~17 hours with the default 60s block time for HSCs - int randomxInterval = GetArg("-ac_randomx_interval",1024); - // This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs - int randomxBlockLag = GetArg("-ac_randomx_lag", 64); // fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag); rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height); From b7adb511a63a65d7691b938bbdd167366c3be63a Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Nov 2022 19:13:31 -0500 Subject: [PATCH 12/13] cleanup --- src/miner.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index bdf10ec56..2fbe958e7 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1089,7 +1089,6 @@ void static RandomXMiner() return; } - char randomxHash[RANDOMX_HASH_SIZE]; rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific @@ -1153,7 +1152,6 @@ void static RandomXMiner() Mining_start = (uint32_t)time(NULL); } - // fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag); rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height); // Use the initial key at the start of the chain, until the first key block @@ -1168,7 +1166,6 @@ void static RandomXMiner() randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey); rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str()); - } //TODO: this is hardcoded to use 2 threads instead of the number of mining threads @@ -1302,7 +1299,7 @@ void static RandomXMiner() rxdebug("%s: Checking solution against target\n"); pblock->nSolution = soln; solutionTargetChecks.increment(); - fprintf(stderr,"%s: solutionTargetChecks=%lu\n", __func__, solutionTargetChecks.get()); + // fprintf(stderr,"%s: solutionTargetChecks=%lu\n", __func__, solutionTargetChecks.get()); B = *pblock; h = UintToArith256(B.GetHash()); @@ -1683,7 +1680,7 @@ void static BitcoinMiner() LogPrint("pow", "- Checking solution against target\n"); pblock->nSolution = soln; solutionTargetChecks.increment(); - rxdebug("%s: solutionTargetChecks=%lu\n", solutionTargetChecks.get()); + // fprintf(stderr, "%s: solutionTargetChecks=%lu\n", __func__, solutionTargetChecks.get()); B = *pblock; h = UintToArith256(B.GetHash()); /*for (z=31; z>=16; z--) From 01ff5c81f61746b7c5ceabb19b10215b8f617da2 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 6 Dec 2022 14:23:53 -0500 Subject: [PATCH 13/13] Improve some comments and ensure backcompat on HUSH mainnet Some comments turned out to be wrong and some could be more helpful. It turns out that when AveragingWindowTimespan was changed to fix a HUSH mainnet bug long ago, that introduced a bug for HSC's that do not use a 75s block time. Since the default is 60s that likely means all HSC's that will be created. There were no production HSC's in use at the time of that bugfix, so the bug went unnoticed until DRAGONX was launched. The bug then manifested as the DRAGONX difficulty bug, which cause the difficulty to never correct down, only up and lead to extremely long block times on DRAGONX mainnet. This code change ensures that HUSH mainnet uses the same hardcoded AWT as it did previously and all other HSC's will use params.AveragingWindowTimespan() , including DRAGONX mainnet. This seems less dangerous than changing AveragingWindowTimespan() on HUSH mainnet. --- src/pow.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pow.cpp b/src/pow.cpp index 31c9eafcf..a63ac8d21 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -509,8 +509,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead } // Changing this requires changing many other things and -// changes consensus. Have fun -- Duke -int64_t AveragingWindowTimespan(int32_t height) { +// might change consensus. Have fun -- Duke +// NOTE: Ony HUSH3 mainnet should use this function, all HSC's should use params.AveragigWindowTimespan() +int64_t AveragingWindowTimespan() { // used in const methods, beware! // This is the correct AWT for 75s blocktime, before block 340k // the correct value was 2550 when the blocktime was 150s @@ -527,9 +528,9 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime; LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan); - //NOTE: this will break HUSH+DRAGONX mainnet! For testing only. - int64_t AWT = params.AveragingWindowTimespan(); - //int64_t AWT = AveragingWindowTimespan(height) ; + bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false; + // If this is HUSH3, use AWT function defined above, else use the one in params + int64_t AWT = ishush3 ? AveragingWindowTimespan() : params.AveragingWindowTimespan(); nActualTimespan = AWT + (nActualTimespan - AWT)/4; LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan);