Browse Source

Significant mining optimization and POS DAA modification

pull/4/head
Michael Toutonghi 6 years ago
parent
commit
dbe656fe39
  1. 4
      src/komodo_globals.h
  2. 5
      src/main.cpp
  3. 75
      src/miner.cpp
  4. 120
      src/pow.cpp

4
src/komodo_globals.h

@ -80,8 +80,10 @@ uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH;
// Verus proof of stake controls
int32_t ASSETCHAINS_LWMAPOS = 0; // percentage of blocks should be PoS
int32_t VERUS_BLOCK_POSUNITS = 1000; // one block is 1000 units
int32_t VERUS_BLOCK_POSUNITS = 1024; // one block is 1000 units
int32_t VERUS_MIN_STAKEAGE = 150; // 1/2 this should also be a cap on the POS averaging window, or startup could be too easy
int32_t VERUS_MAX_CONSECUTIVE_POS = 7;
int32_t VERUS_NOPOS_THRESHHOLD = 150; // if we have no POS blocks in this many blocks, set to default difficulty
uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10;

5
src/main.cpp

@ -5622,10 +5622,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
return true;
}
if (strCommand == "version")
{
// Each connection can only send one version message

75
src/miner.cpp

@ -1017,23 +1017,19 @@ void static BitcoinMiner_noeq()
waitForPeers(chainparams);
CBlockIndex *pindexPrev, *pindexCur;
do {
{
LOCK(cs_main);
pindexPrev = chainActive.Tip();
}
pindexPrev = chainActive.Tip();
MilliSleep(5000 + rand() % 5000);
{
LOCK(cs_main);
pindexCur = chainActive.Tip();
}
pindexCur = chainActive.Tip();
} while (pindexPrev != pindexCur);
printf("Mining height %d\n", chainActive.Tip()->nHeight + 1);
// this will not stop printing more than once in all cases, but it will allow us to print in all cases
// and print duplicates rarely without having to synchronize
static CBlockIndex *lastChainTipPrinted;
miningTimer.start();
try {
fprintf(stderr,"Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
while (true)
{
miningTimer.stop();
@ -1050,7 +1046,6 @@ void static BitcoinMiner_noeq()
MilliSleep(5000 + rand() % 5000);
} while (pindexPrev != chainActive.Tip());
}
miningTimer.start();
// Create new block
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
@ -1060,7 +1055,13 @@ void static BitcoinMiner_noeq()
Mining_start = (uint32_t)time(NULL);
}
//fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height);
if (lastChainTipPrinted != pindexPrev)
{
printf("Mining height %d\n", Mining_height);
lastChainTipPrinted = pindexPrev;
}
miningTimer.start();
#ifdef ENABLE_WALLET
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey);
@ -1074,6 +1075,7 @@ void static BitcoinMiner_noeq()
fprintf(stderr,"created illegal block, retry\n");
continue;
}
unique_ptr<CBlockTemplate> pblocktemplate(ptr);
if (!pblocktemplate.get())
{
@ -1118,7 +1120,11 @@ void static BitcoinMiner_noeq()
if ( pindexPrev != chainActive.Tip() )
{
printf("Block %d added to chain\n", chainActive.Tip()->nHeight);
if (lastChainTipPrinted != chainActive.Tip())
{
lastChainTipPrinted = chainActive.Tip();
printf("Block %d added to chain\n", lastChainTipPrinted->nHeight);
}
MilliSleep(250);
continue;
}
@ -1134,13 +1140,17 @@ void static BitcoinMiner_noeq()
while (true)
{
// for speed check multiples at a time
for (int i = 0; i < ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]; i++)
arith_uint256 arNonce = UintToArith256(pblock->nNonce);
// for speed check 16 mega hash at a time
for (int i = 0; i < 0x1000000; i++)
{
solutionTargetChecks.increment();
// Update nNonce and nTime
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
// Update nNonce
*((unsigned char *)&(pblock->nNonce)) = i & 0xff;
*(((unsigned char *)&(pblock->nNonce))+1) = (i >> 8) & 0xff;
*(((unsigned char *)&(pblock->nNonce))+2) = (i >> 16) & 0xff;
if ( UintToArith256(pblock->GetHash()) <= hashTarget )
{
@ -1165,17 +1175,18 @@ void static BitcoinMiner_noeq()
ProcessBlockFound(pblock));
#endif
SetThreadPriority(THREAD_PRIORITY_LOWEST);
// In regression test mode, stop mining after a block is found.
if (chainparams.MineBlocksOnDemand()) {
throw boost::thread_interrupted();
}
break;
}
else
// check periodically if we're stale
if (!(i % ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]))
{
if ((UintToArith256(pblock->nNonce) & mask) == mask)
if ( pindexPrev != chainActive.Tip() )
{
if (lastChainTipPrinted != chainActive.Tip())
{
lastChainTipPrinted = chainActive.Tip();
printf("Block %d added to chain\n", lastChainTipPrinted->nHeight);
}
break;
}
}
@ -1193,21 +1204,25 @@ void static BitcoinMiner_noeq()
}
}
if ((UintToArith256(pblock->nNonce) & mask) == mask)
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
{
fprintf(stderr,"%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576);
fprintf(stderr,"timeout, retrying\n");
break;
}
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
if ( pindexPrev != chainActive.Tip() )
{
fprintf(stderr,"timeout, retrying\n");
if (lastChainTipPrinted != chainActive.Tip())
{
lastChainTipPrinted = chainActive.Tip();
printf("Block %d added to chain\n", lastChainTipPrinted->nHeight);
}
break;
}
if ( pindexPrev != chainActive.Tip() )
if ((UintToArith256(pblock->nNonce) & mask) == mask)
{
printf("Block %d added to chain\n", chainActive.Tip()->nHeight);
printf("%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576);
break;
}

120
src/pow.cpp

@ -22,7 +22,7 @@
uint32_t komodo_chainactive_timestamp();
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH;
extern int32_t VERUS_BLOCK_POSUNITS;
extern int32_t VERUS_BLOCK_POSUNITS, VERUS_MAX_CONSECUTIVE_POS, VERUS_NOPOS_THRESHHOLD;
unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params);
unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);
@ -157,55 +157,131 @@ bool DoesHashQualify(const CBlockIndex *pbindex)
// the goal is to keep POS at a solve time that is a ratio of block time units. the low resolution makes a stable solution more challenging
// and requires that the averaging window be quite long.
unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
uint32_t lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
{
arith_uint256 nextTarget {0}, sumTarget {0}, bnTmp, bnLimit;
bnLimit = UintToArith256(params.posLimit);
unsigned int nProofOfStakeLimit = bnLimit.GetCompact();
uint32_t nProofOfStakeLimit = bnLimit.GetCompact();
int64_t t = 0, solvetime = 0;
int64_t k = params.nLwmaPOSAjustedWeight;
int64_t N = params.nPOSAveragingWindow;
struct solveSequence {
bool consecutive;
uint32_t solveTime;
uint32_t nBits;
solveSequence()
{
consecutive = 0;
solveTime = 0;
nBits = 0;
}
};
// Find the first block in the averaging interval as we total the linearly weighted average
// of POS solve times
const CBlockIndex* pindexFirst = pindexLast;
const CBlockIndex* pindexNext;
std::vector<solveSequence> idx;
// we need to make sure we have a starting nBits reference, which is either the last POS block, or the default
// if we have had no POS block in the threshold number of blocks, we must return the default, otherwise, we'll now have
// a starting point
uint32_t nBits = nProofOfStakeLimit;
for (int i = 0; i < VERUS_NOPOS_THRESHHOLD; i++)
{
if (!pindexFirst)
return nProofOfStakeLimit;
int64_t t = 0, solvetime = 0, k = params.nLwmaPOSAjustedWeight, N = params.nPOSAveragingWindow;
CBlockHeader hdr = pindexFirst->GetBlockHeader();
for (int i = 0, j = N - 1; pindexFirst && i < N; i++, j--) {
pindexNext = pindexFirst;
if (hdr.IsVerusPOSBlock())
{
nBits = hdr.GetVerusPOSTarget();
break;
}
pindexFirst = pindexFirst->pprev;
}
pindexFirst = pindexLast;
idx.resize(N);
for (int i = N - 1; i >= 0; i--)
{
// we measure our solve time in passing of blocks, where one bock == VERUS_BLOCK_POSUNITS units
for (int x = 0; x < params.nPOSAveragingWindow; x++)
// consecutive blocks in either direction have their solve times exponentially multiplied or divided by power of 2
int x;
for (x = 0; x < VERUS_MAX_CONSECUTIVE_POS; x++)
{
solvetime += VERUS_BLOCK_POSUNITS;
pindexFirst = pindexFirst->pprev;
// in this loop, unqualified blocks are assumed POS
if (!pindexFirst || !DoesHashQualify(pindexFirst))
if (!pindexFirst)
return nProofOfStakeLimit;
CBlockHeader hdr = pindexFirst->GetBlockHeader();
if (hdr.IsVerusPOSBlock())
{
nBits = hdr.GetVerusPOSTarget();
break;
}
}
if (!pindexFirst)
break;
if (x)
{
idx[i].consecutive = false;
idx[i].solveTime = VERUS_BLOCK_POSUNITS << x;
idx[i].nBits = nBits;
}
else
{
idx[i].consecutive = true;
idx[i].nBits = nBits;
// go forward and halve the minimum solve time for all consecutive blocks in this run, to get here, our last block is POS,
// and if there is no POS block in front of it, it gets the normal solve time of one block
uint32_t st = VERUS_BLOCK_POSUNITS << 1;
for (int j = i; j < N; j++)
{
if (idx[j].consecutive == true)
{
st >>= 1;
}
else
break;
}
for (int j = i; j < N; j++)
{
if (idx[j].consecutive == true)
idx[j].solveTime = st;
if ((j - i) >= VERUS_MAX_CONSECUTIVE_POS)
{
// target of 0 (virtually impossible), if we hit max consecutive POS blocks
nextTarget.SetCompact(0);
return nextTarget.GetCompact();
}
else
break;
}
}
}
for (int i = N - 1; i >= 0; i--)
{
// weighted sum
t += solvetime * j;
t += idx[i].solveTime * i;
// Target sum divided by a factor, (k N^2).
// The factor is a part of the final equation. However we divide
// here to avoid potential overflow.
bnTmp.SetCompact(pindexNext->nBits); // TODO(miketout): this must be POS nBits
bnTmp.SetCompact(idx[i].nBits);
sumTarget += bnTmp / (k * N * N);
}
// Check we have enough blocks
if (!pindexFirst)
return nProofOfStakeLimit;
// Keep t reasonable in case strange solvetimes occurred.
if (t < N * k / 3)
t = N * k / 3;
bnTmp = bnLimit;
nextTarget = t * sumTarget;
if (nextTarget > bnTmp)
nextTarget = bnTmp;
if (nextTarget > bnLimit)
nextTarget = bnLimit;
return nextTarget.GetCompact();
}

Loading…
Cancel
Save