diff --git a/src/miner.cpp b/src/miner.cpp index 92acea2d9..2fbe958e7 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1067,6 +1067,42 @@ void static RandomXMiner() ); 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; + 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"); + + 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; + } + + 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); @@ -1115,6 +1151,38 @@ void static RandomXMiner() Mining_height = pindexPrev->GetHeight()+1; 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 + 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 + 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); + if(myVM == NULL) { + LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n"); + return; + } //fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start); #ifdef ENABLE_WALLET CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, 0); @@ -1168,6 +1236,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)); @@ -1181,8 +1250,8 @@ void static RandomXMiner() HASHTarget = arith_uint256().SetCompact(savebits); roundrobin_delay = ROUNDROBIN_DELAY; Mining_start = 0; - gotinvalid = 0; + while (true) { if ( gotinvalid != 0 ) { @@ -1196,13 +1265,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^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; @@ -1211,49 +1273,9 @@ 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 - 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()); - } - - randomx_vm *myVM = randomx_create_vm(flags, randomxCache, NULL); - 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("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,8 +1285,8 @@ void static RandomXMiner() printf("\n"); } - // Use randomx hash to build a valid block + // Use randomx hash to build a valid block std::function)> validBlock = #ifdef ENABLE_WALLET [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams] @@ -1277,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()); @@ -1371,7 +1393,14 @@ 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"); + } + + } catch (const boost::thread_interrupted&) { miningTimer.stop(); c.disconnect(); @@ -1383,6 +1412,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(); } @@ -1646,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--) @@ -1859,6 +1893,7 @@ void static BitcoinMiner() LogPrintf("HushMiner runtime error: %s\n", e.what()); return; } + miningTimer.stop(); c.disconnect(); } diff --git a/src/pow.cpp b/src/pow.cpp index 753378ba9..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 @@ -526,7 +527,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) ; + + 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); 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..6a1c9e86f --- /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 -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..9571566a2 --- /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 -debug=pow $@