|
|
|
|
@@ -58,6 +58,8 @@
|
|
|
|
|
#endif
|
|
|
|
|
#include <mutex>
|
|
|
|
|
|
|
|
|
|
#define rxdebug(format, ...) if(fRandomXDebug) { fprintf(stderr, format, __func__, ## __VA_ARGS__ ); }
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
@@ -117,6 +119,7 @@ public:
|
|
|
|
|
|
|
|
|
|
extern int8_t ASSETCHAINS_ADAPTIVEPOW;
|
|
|
|
|
extern uint32_t ASSETCHAINS_RANDOMX;
|
|
|
|
|
extern bool fRandomXDebug;
|
|
|
|
|
|
|
|
|
|
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
|
|
|
|
|
{
|
|
|
|
|
@@ -411,7 +414,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
|
|
|
|
Notarizations++;
|
|
|
|
|
if ( Notarizations > 1 )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "skipping notarization.%d\n",Notarizations);
|
|
|
|
|
fprintf(stderr, "%s: skipping notarization.%d\n",__func__, Notarizations);
|
|
|
|
|
// Any attempted notarization needs to be in its own block!
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
@@ -604,7 +607,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
|
|
|
|
blocktime = 1 + std::max(pindexPrev->GetMedianTimePast()+1, GetTime());
|
|
|
|
|
else blocktime = 1 + std::max((int64_t)(pindexPrev->nTime+1), GetTime());
|
|
|
|
|
//pblock->nTime = blocktime + 1;
|
|
|
|
|
fprintf(stderr,"%s: calling GetNextWorkRequired\n", __func__);
|
|
|
|
|
// fprintf(stderr,"%s: calling GetNextWorkRequired\n", __func__);
|
|
|
|
|
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
|
|
|
|
|
|
|
|
|
|
LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x\n", nBlockSize,blocktime,pblock->nBits);
|
|
|
|
|
@@ -618,7 +621,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
|
|
|
|
txNew.vout.resize(1);
|
|
|
|
|
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
|
|
|
|
|
txNew.vout[0].nValue = GetBlockSubsidy(nHeight,consensusParams) + nFees;
|
|
|
|
|
fprintf(stderr,"%s: mine ht.%d with %.8f\n",__func__,nHeight,(double)txNew.vout[0].nValue/COIN);
|
|
|
|
|
// fprintf(stderr,"%s: mine ht.%d with %.8f\n",__func__,nHeight,(double)txNew.vout[0].nValue/COIN);
|
|
|
|
|
txNew.nExpiryHeight = 0;
|
|
|
|
|
if ( ASSETCHAINS_ADAPTIVEPOW <= 0 )
|
|
|
|
|
txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetTime());
|
|
|
|
|
@@ -701,7 +704,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
|
|
|
|
// if not staking, setup nonce, otherwise, leave it alone
|
|
|
|
|
if (!isStake || ASSETCHAINS_LWMAPOS == 0)
|
|
|
|
|
{
|
|
|
|
|
// Randomise nonce
|
|
|
|
|
// Randomize nonce
|
|
|
|
|
arith_uint256 nonce = UintToArith256(GetRandHash());
|
|
|
|
|
|
|
|
|
|
// Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters)
|
|
|
|
|
@@ -749,9 +752,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
|
|
|
|
pblocktemplate->vTxFees[0] = -nFees;
|
|
|
|
|
//*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees;
|
|
|
|
|
//fprintf(stderr,"added notaryvin\n");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n");
|
|
|
|
|
if ( SMART_CHAIN_SYMBOL[0] == 0 || (SMART_CHAIN_SYMBOL[0] != 0 && !isStake) )
|
|
|
|
|
{
|
|
|
|
|
@@ -764,7 +765,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
|
|
|
|
else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (SMART_CHAIN_SYMBOL[0] != 0 || IS_HUSH_NOTARY == 0 || My_notaryid < 0) )
|
|
|
|
|
{
|
|
|
|
|
CValidationState state;
|
|
|
|
|
fprintf(stderr,"%s: check validity\n", __func__);
|
|
|
|
|
//fprintf(stderr,"%s: check validity\n", __func__);
|
|
|
|
|
if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) // invokes CC checks
|
|
|
|
|
{
|
|
|
|
|
if ( SMART_CHAIN_SYMBOL[0] == 0 || (SMART_CHAIN_SYMBOL[0] != 0 && !isStake) )
|
|
|
|
|
@@ -795,7 +796,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
|
|
|
|
|
|
|
|
|
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,"RandomXMiner: %s with nExtraNonce=%u\n", __func__, nExtraNonce);
|
|
|
|
|
//fprintf(stderr,"RandomXMiner: %s with nExtraNonce=%u\n", __func__, nExtraNonce);
|
|
|
|
|
// Update nExtraNonce
|
|
|
|
|
static uint256 hashPrevBlock;
|
|
|
|
|
if (hashPrevBlock != pblock->hashPrevBlock)
|
|
|
|
|
@@ -819,14 +820,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
|
|
|
|
|
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake)
|
|
|
|
|
{
|
|
|
|
|
CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i,len;
|
|
|
|
|
fprintf(stderr,"%s: with nHeight=%d\n", __func__, nHeight);
|
|
|
|
|
// fprintf(stderr,"%s: with nHeight=%d\n", __func__, nHeight);
|
|
|
|
|
if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 )
|
|
|
|
|
{
|
|
|
|
|
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
|
|
|
|
|
{
|
|
|
|
|
pubkey = ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY);
|
|
|
|
|
scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG;
|
|
|
|
|
fprintf(stderr,"%s: with pubkey=%s\n", __func__, HexStr(pubkey).c_str() );
|
|
|
|
|
// fprintf(stderr,"%s: with pubkey=%s\n", __func__, HexStr(pubkey).c_str() );
|
|
|
|
|
} else {
|
|
|
|
|
len = strlen(ASSETCHAINS_SCRIPTPUB.c_str());
|
|
|
|
|
len >>= 1;
|
|
|
|
|
@@ -863,7 +864,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fprintf(stderr,"%s: calling CreateNewBlock\n", __func__);
|
|
|
|
|
// fprintf(stderr,"%s: calling CreateNewBlock\n", __func__);
|
|
|
|
|
return CreateNewBlock(pubkey, scriptPubKey, gpucount, isStake);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1067,11 +1068,15 @@ void static RandomXMiner()
|
|
|
|
|
miningTimer.start();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
fprintf(stderr,"RandomXMiner: mining %s with randomx\n",SMART_CHAIN_SYMBOL);
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: mining %s with randomx\n",SMART_CHAIN_SYMBOL);
|
|
|
|
|
|
|
|
|
|
rxdebug("%s: mining %s with randomx\n", SMART_CHAIN_SYMBOL);
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,"RandomXMiner: beginning mining loop on %s with nExtraNonce=%u\n",SMART_CHAIN_SYMBOL, nExtraNonce);
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: beginning mining loop on %s with nExtraNonce=%u\n",SMART_CHAIN_SYMBOL, nExtraNonce);
|
|
|
|
|
rxdebug("%s: start mining loop on %s with nExtraNonce=%u\n", SMART_CHAIN_SYMBOL, nExtraNonce);
|
|
|
|
|
|
|
|
|
|
if (chainparams.MiningRequiresPeers()) {
|
|
|
|
|
//if ( ASSETCHAINS_SEED != 0 && chainActive.LastTip()->GetHeight() < 100 )
|
|
|
|
|
// break;
|
|
|
|
|
@@ -1102,14 +1107,15 @@ void static RandomXMiner()
|
|
|
|
|
Mining_height = pindexPrev->GetHeight()+1;
|
|
|
|
|
Mining_start = (uint32_t)time(NULL);
|
|
|
|
|
}
|
|
|
|
|
fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start);
|
|
|
|
|
//fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start);
|
|
|
|
|
#ifdef ENABLE_WALLET
|
|
|
|
|
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, 0);
|
|
|
|
|
#else
|
|
|
|
|
CBlockTemplate *ptr = CreateNewBlockWithKey();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
fprintf(stderr,"RandomXMiner: created new block\n");
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: created new block with Mining_start=%u\n",Mining_start);
|
|
|
|
|
rxdebug("%s: created new block with Mining_start=%u\n",Mining_start);
|
|
|
|
|
if ( ptr == 0 )
|
|
|
|
|
{
|
|
|
|
|
if ( !GetBoolArg("-gen",false))
|
|
|
|
|
@@ -1125,7 +1131,9 @@ void static RandomXMiner()
|
|
|
|
|
sleep(1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
fprintf(stderr,"RandomXMiner: getting block template\n");
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: getting block template\n");
|
|
|
|
|
rxdebug("%s: getting block template\n");
|
|
|
|
|
|
|
|
|
|
unique_ptr<CBlockTemplate> pblocktemplate(ptr);
|
|
|
|
|
if (!pblocktemplate.get())
|
|
|
|
|
{
|
|
|
|
|
@@ -1153,7 +1161,7 @@ void static RandomXMiner()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
|
|
|
|
|
fprintf(stderr,"RandomXMiner: %u transactions in block\n",(int32_t)pblock->vtx.size());
|
|
|
|
|
// 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));
|
|
|
|
|
|
|
|
|
|
// Search
|
|
|
|
|
@@ -1175,7 +1183,8 @@ void static RandomXMiner()
|
|
|
|
|
}
|
|
|
|
|
hush_longestchain();
|
|
|
|
|
|
|
|
|
|
fprintf(stderr,"RandomXMiner: solving with nNonce = %s\n",pblock->nNonce.ToString().c_str());
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: solving with nNonce = %s\n",pblock->nNonce.ToString().c_str());
|
|
|
|
|
rxdebug("%s: solving with nNonce = %s\n",pblock->nNonce.ToString().c_str());
|
|
|
|
|
arith_uint256 hashTarget;
|
|
|
|
|
hashTarget = HASHTarget;
|
|
|
|
|
|
|
|
|
|
@@ -1190,8 +1199,9 @@ void static RandomXMiner()
|
|
|
|
|
// Use the current block as randomx input
|
|
|
|
|
randomxInput << pblocktemplate->block;
|
|
|
|
|
|
|
|
|
|
std::cerr << "RandomXMiner: randomxInput=" << HexStr(randomxInput) << "\n";
|
|
|
|
|
fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput);
|
|
|
|
|
// std::cerr << "RandomXMiner: randomxInput=" << HexStr(randomxInput) << "\n";
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput);
|
|
|
|
|
rxdebug("%s: randomxKey=%s randomxInput=%s", randomxKey, HexStr(randomxInput).c_str());
|
|
|
|
|
|
|
|
|
|
randomx_flags flags = randomx_get_flags();
|
|
|
|
|
randomx_cache *randomxCache = randomx_alloc_cache(flags);
|
|
|
|
|
@@ -1208,43 +1218,43 @@ void static RandomXMiner()
|
|
|
|
|
// 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);
|
|
|
|
|
fprintf(stderr,"RandomXMiner: Mining_height=%u\n", Mining_height);
|
|
|
|
|
// 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);
|
|
|
|
|
fprintf(stderr,"RandomXMiner: initialized cache with initial key\n");
|
|
|
|
|
rxdebug("%s: initialized cache with initial key\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,"RandomXMiner: calculating keyHeight with randomxInterval=%d\n", randomxInterval);
|
|
|
|
|
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;
|
|
|
|
|
fprintf(stderr,"RandomXMiner: key height=%d\n", keyHeight);
|
|
|
|
|
uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash();
|
|
|
|
|
|
|
|
|
|
randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey);
|
|
|
|
|
fprintf(stderr,"RandomXMiner: initialized cache with randomxBlockKey=%s\n", randomxBlockKey.ToString().c_str());
|
|
|
|
|
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) {
|
|
|
|
|
fprintf(stderr,"RandomXMiner: Cannot create RandomX VM, aborting!\n");
|
|
|
|
|
LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: created VM\n");
|
|
|
|
|
|
|
|
|
|
randomx_calculate_hash(myVM, &randomxInput, sizeof randomxInput, randomxHash);
|
|
|
|
|
fprintf(stderr,"RandomXMiner: calculated randomx hash\n");
|
|
|
|
|
// rxdebug("calculated randomx hash\n");
|
|
|
|
|
|
|
|
|
|
randomx_destroy_vm(myVM);
|
|
|
|
|
// fprintf(stderr,"RandomXMiner: destroyed VM\n");
|
|
|
|
|
randomx_release_cache(randomxCache);
|
|
|
|
|
|
|
|
|
|
printf("RandomXMiner: randomxHash=");
|
|
|
|
|
for (unsigned i = 0; i < RANDOMX_HASH_SIZE; ++i) {
|
|
|
|
|
printf("%02x", randomxHash[i] & 0xff);
|
|
|
|
|
}
|
|
|
|
|
rxdebug("%s: randomxHash=");
|
|
|
|
|
if (fRandomXDebug) {
|
|
|
|
|
for (unsigned i = 0; i < RANDOMX_HASH_SIZE; ++i) {
|
|
|
|
|
printf("%02x", randomxHash[i] & 0xff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
// Use randomx hash to build a valid block
|
|
|
|
|
|
|
|
|
|
std::function<bool(std::vector<unsigned char>)> validBlock =
|
|
|
|
|
@@ -1256,23 +1266,25 @@ void static RandomXMiner()
|
|
|
|
|
(std::vector<unsigned char> soln) {
|
|
|
|
|
int32_t z; arith_uint256 h; CBlock B;
|
|
|
|
|
// Write the solution to the hash and compute the result.
|
|
|
|
|
fprintf(stderr,"RandomXMiner: Checking solution against target\n");
|
|
|
|
|
rxdebug("%s: Checking solution against target\n");
|
|
|
|
|
pblock->nSolution = soln;
|
|
|
|
|
solutionTargetChecks.increment();
|
|
|
|
|
B = *pblock;
|
|
|
|
|
h = UintToArith256(B.GetHash());
|
|
|
|
|
|
|
|
|
|
fprintf(stderr,"RandomXMiner: h=");
|
|
|
|
|
for (z=31; z>=0; z--)
|
|
|
|
|
fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
|
|
|
|
|
fprintf(stderr," , hashTarget=");
|
|
|
|
|
for (z=31; z>=0; z--)
|
|
|
|
|
fprintf(stderr,"%02x",((uint8_t *)&hashTarget)[z]);
|
|
|
|
|
fprintf(stderr,"\n");
|
|
|
|
|
rxdebug("%s: h=");
|
|
|
|
|
if (fRandomXDebug) {
|
|
|
|
|
for (z=31; z>=0; z--)
|
|
|
|
|
fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
|
|
|
|
|
fprintf(stderr," , hashTarget=");
|
|
|
|
|
for (z=31; z>=0; z--)
|
|
|
|
|
fprintf(stderr,"%02x",((uint8_t *)&hashTarget)[z]);
|
|
|
|
|
fprintf(stderr,"\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( h > hashTarget )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,"RandomXMiner: h > hashTarget");
|
|
|
|
|
rxdebug("%s: h > hashTarget");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1318,12 +1330,12 @@ void static RandomXMiner()
|
|
|
|
|
std::vector<unsigned char> sol_char(randomxHash, randomxHash+32);
|
|
|
|
|
bool found = validBlock(sol_char);
|
|
|
|
|
if (found) {
|
|
|
|
|
fprintf(stderr,"RandomXMiner: found solution!\n");
|
|
|
|
|
rxdebug("%s: found solution!\n");
|
|
|
|
|
// If we find a POW solution, do not try other solutions
|
|
|
|
|
// because they become invalid as we created a new block in blockchain.
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr,"RandomXMiner: solution not found, validBlock=false\n");
|
|
|
|
|
rxdebug("%s: solution not found, validBlock=false\n");
|
|
|
|
|
}
|
|
|
|
|
} catch (RandomXSolverCanceledException&) {
|
|
|
|
|
LogPrintf("HushRandomXMiner solver canceled\n");
|
|
|
|
|
|