1010#include < chain.h>
1111// #include <logging.h>
1212#include < primitives/block.h>
13+ #include < sync.h>
1314#include < uint256.h>
1415
15- #include < atomic>
16+ #include < mutex>
17+
18+ RecursiveMutex cs_target_cache;
1619
1720// peercoin: find last block index up to pindex
1821static inline const CBlockIndex* GetLastBlockIndex (const CBlockIndex* pindex, const bool fProofOfStake )
@@ -186,19 +189,6 @@ unsigned int WeightedTargetExponentialMovingAverage(const CBlockIndex* pindexLas
186189 return bnNew.GetCompactRounded ();
187190}
188191
189- static inline void Arith256ToAtomic (const arith_uint256& arith, std::atomic<uint64_t >& first, std::atomic<uint64_t >& second, std::atomic<uint64_t >& third, std::atomic<uint64_t >& fourth)
190- {
191- first.store (arith.GetLow64 ());
192- second.store ((arith >> 64 ).GetLow64 ());
193- third.store ((arith >> 128 ).GetLow64 ());
194- fourth.store ((arith >> 192 ).GetLow64 ());
195- }
196-
197- static inline void AtomicToArith256 (arith_uint256& arith, const std::atomic<uint64_t >& first, const std::atomic<uint64_t >& second, const std::atomic<uint64_t >& third, const std::atomic<uint64_t >& fourth)
198- {
199- arith = arith_uint256 (first.load ()) | (arith_uint256 (second.load ()) << 64 ) | (arith_uint256 (third.load ()) << 128 ) | (arith_uint256 (fourth.load ()) << 192 );
200- }
201-
202192unsigned int AverageTargetASERT (const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
203193{
204194 const int algo = CBlockHeader::GetAlgo (pblock->nVersion );
@@ -244,69 +234,65 @@ unsigned int AverageTargetASERT(const CBlockIndex* pindexLast, const CBlockHeade
244234 arith_uint256 refBlockTarget;
245235
246236 // We don't want to recalculate the average of several days' worth of block targets here every single time, so instead we cache the average and start height
247- const bool fUseCache = false ;
248- arith_uint256 refBlockTargetCache;
249- // For lack of a better way to store an atomic uint256 at the moment
250- static std::atomic< uint64_t > targetCacheOne{ 0 };
251- static std::atomic< uint64_t > targetCacheTwo{ 0 } ;
252- static std::atomic< uint64_t > targetCacheThree{ 0 } ;
253- static std::atomic< uint64_t > targetCacheFour{ 0 } ;
254- static std::atomic_int nTargetCacheHeight{- 1 };
255- static std::atomic_int nTargetCacheAlgo{CBlockHeader::ALGO_COUNT};
256- if (fUseCache )
257- AtomicToArith256 (refBlockTargetCache, targetCacheOne, targetCacheTwo, targetCacheThree, targetCacheFour) ;
258-
259- if (nASERTBlockTargetsToAverage > 0 && nHeight >= nASERTStartHeight + nASERTBlockTargetsToAverage && nHeightDiff >= nASERTBlockTargetsToAverage) {
260- if (! fUseCache || nTargetCacheHeight. load () != ( int )(nHeightDiff / nASERTBlockTargetsToAverage) || nTargetCacheAlgo. load () != algo || refBlockTargetCache == arith_uint256 () || algo == - 1 ) {
261- const uint32_t nBlocksToSkip = nHeightDiff % nASERTBlockTargetsToAverage;
262- const CBlockIndex* pindex = pindexPrev ;
263- // LogPrintf("nBlocksToSkip = %u\n", nBlocksToSkip);
264-
265- for ( unsigned int i = 0 ; i < nBlocksToSkip; i++) {
266- pindex = algo == - 1 ? GetLastBlockIndex (pindex-> pprev , fProofOfStake ) : GetLastBlockIndexForAlgo (pindex-> pprev , algo) ;
267- }
268- // LogPrintf("begin pindex->nHeight = %i\n", pindex->nHeight);
269-
270- // unsigned int nBlocksAveraged = 0 ;
271- for ( int i = 0 ; i < ( int )nASERTBlockTargetsToAverage; i++) {
272- if (pindex-> nBits != (nProofOfWorkLimit - 1 ) || !params. fPowAllowMinDifficultyBlocks ) { // Don't add min difficulty targets to the average
273- arith_uint256 bnTarget = arith_uint256 (). SetCompact (pindex-> nBits );
274- refBlockTarget += bnTarget / nASERTBlockTargetsToAverage;
275- // nBlocksAveraged++;
276- // if (pindex->GetBlockHash() == params.hashGenesisBlock)
277- // LogPrintf("Averaging genesis block target\n");
278- } else
279- i--; // Average one more block to make up for the one we skipped
280- pindex = algo == - 1 ? GetLastBlockIndex (pindex-> pprev , fProofOfStake ) : GetLastBlockIndexForAlgo (pindex-> pprev , algo );
281- if (!pindex)
282- break ;
283- }
284- // LogPrintf("nBlocksAveraged = %u\n", nBlocksAveraged);
285- // assert(nBlocksAveraged == nASERTBlockTargetsToAverage) ;
286- // if (pindex)
287- // LogPrintf("end pindex->nHeight = %i\n", pindex->nHeight) ;
288- if ( fUseCache ) {
289- Arith256ToAtomic (refBlockTarget, targetCacheOne, targetCacheTwo, targetCacheThree, targetCacheFour);
290- nTargetCacheHeight. store (nHeightDiff / nASERTBlockTargetsToAverage);
291- nTargetCacheAlgo. store (algo) ;
292- // LogPrintf("Set average target cache at nHeight = %u with algo = %i\n", nHeight, algo);
237+ const bool fUseCache = true ;
238+ {
239+ LOCK (cs_target_cache);
240+
241+ static arith_uint256 refBlockTargetCache ;
242+ static int nTargetCacheHeight = - 1 ;
243+ static int nTargetCacheAlgo = CBlockHeader::ALGO_COUNT ;
244+
245+ if (nASERTBlockTargetsToAverage > 0 && nHeight >= nASERTStartHeight + nASERTBlockTargetsToAverage && nHeightDiff >= nASERTBlockTargetsToAverage) {
246+ if (! fUseCache || nTargetCacheHeight != ( int )(nHeightDiff / nASERTBlockTargetsToAverage) || nTargetCacheAlgo != algo || refBlockTargetCache == arith_uint256 () || algo == - 1 ) {
247+ const uint32_t nBlocksToSkip = nHeightDiff % nASERTBlockTargetsToAverage ;
248+ const CBlockIndex* pindex = pindexPrev;
249+ // LogPrintf("nBlocksToSkip = %u\n", nBlocksToSkip);
250+
251+ for ( unsigned int i = 0 ; i < nBlocksToSkip; i++) {
252+ pindex = algo == - 1 ? GetLastBlockIndex (pindex-> pprev , fProofOfStake ) : GetLastBlockIndexForAlgo (pindex-> pprev , algo) ;
253+ }
254+ // LogPrintf("begin pindex->nHeight = %i\n", pindex->nHeight);
255+
256+ // unsigned int nBlocksAveraged = 0 ;
257+ for ( int i = 0 ; i < ( int )nASERTBlockTargetsToAverage; i++) {
258+ if ( pindex->nBits != (nProofOfWorkLimit - 1 ) || !params. fPowAllowMinDifficultyBlocks ) { // Don't add min difficulty targets to the average
259+ arith_uint256 bnTarget = arith_uint256 (). SetCompact (pindex-> nBits );
260+ refBlockTarget += bnTarget / nASERTBlockTargetsToAverage ;
261+ // nBlocksAveraged++;
262+ // if (pindex->GetBlockHash() == params.hashGenesisBlock)
263+ // LogPrintf("Averaging genesis block target\n" );
264+ } else
265+ i--; // Average one more block to make up for the one we skipped
266+ pindex = algo == - 1 ? GetLastBlockIndex (pindex->pprev , fProofOfStake ) : GetLastBlockIndexForAlgo (pindex-> pprev , algo);
267+ if (!pindex)
268+ break ;
269+ }
270+ // LogPrintf("nBlocksAveraged = %u\n", nBlocksAveraged );
271+ // assert(nBlocksAveraged == nASERTBlockTargetsToAverage);
272+ // if (pindex)
273+ // LogPrintf("end pindex->nHeight = %i\n", pindex->nHeight);
274+ if ( fUseCache ) {
275+ refBlockTargetCache = refBlockTarget ;
276+ nTargetCacheHeight = nHeightDiff / nASERTBlockTargetsToAverage;
277+ nTargetCacheAlgo = algo ;
278+ // LogPrintf("Set average target cache at nHeight = %u with algo = %i\n", nHeight, algo);
279+ }
280+ } else {
281+ refBlockTarget = refBlockTargetCache ;
282+ // LogPrintf("Using average target cache at nHeight = %u with algo = %i\n", nHeight, algo);
293283 }
294284 } else {
295- refBlockTarget = refBlockTargetCache;
296- // LogPrintf("Using average target cache at nHeight = %u with algo = %i\n", nHeight, algo);
285+ if (fUseCache && algo != -1 ) {
286+ if (nTargetCacheHeight != -1 || nTargetCacheAlgo != algo || refBlockTargetCache == arith_uint256 ()) {
287+ refBlockTargetCache = arith_uint256 ().SetCompact (pindexReferenceBlock->nBits );
288+ nTargetCacheHeight = -1 ;
289+ nTargetCacheAlgo = algo;
290+ // LogPrintf("Set ref target cache at nHeight = %u with algo = %i\n", nHeight, algo);
291+ }
292+ refBlockTarget = refBlockTargetCache;
293+ } else
294+ refBlockTarget = arith_uint256 ().SetCompact (pindexReferenceBlock->nBits );
297295 }
298- } else {
299- if (fUseCache && algo != -1 ) {
300- if (nTargetCacheAlgo.load () != algo || refBlockTargetCache == arith_uint256 ()) {
301- refBlockTargetCache = arith_uint256 ().SetCompact (pindexReferenceBlock->nBits );
302- Arith256ToAtomic (refBlockTargetCache, targetCacheOne, targetCacheTwo, targetCacheThree, targetCacheFour);
303- nTargetCacheHeight.store (-1 );
304- nTargetCacheAlgo.store (algo);
305- // LogPrintf("Set ref target cache at nHeight = %u with algo = %i\n", nHeight, algo);
306- }
307- refBlockTarget = refBlockTargetCache;
308- } else
309- refBlockTarget = arith_uint256 ().SetCompact (pindexReferenceBlock->nBits );
310296 }
311297
312298 // LogPrintf("nHeight = %u, algo = %i, refBlockTarget = %s\n", nHeight, algo, refBlockTarget.ToString().c_str());
@@ -316,9 +302,9 @@ unsigned int AverageTargetASERT(const CBlockIndex* pindexLast, const CBlockHeade
316302 const uint32_t divisor = params.nPowTargetTimespan ; // Must be positive
317303 const int exponent = dividend / divisor; // Note: this integer division rounds down positive and rounds up negative numbers via truncation, but the truncated fractional part is handled by the approximation below
318304 const uint32_t remainder = fPositive ? dividend % divisor : -dividend % divisor; // Must be positive
319- // We are using uint256 rather than uint64_t here because a nPowTargetTimespan of more than 3 days in the divisor may cause the following cubic approximation to overflow a uint64_t
320- arith_uint256 numerator = 1 ;
321- arith_uint256 denominator = 1 ;
305+ // We are using uint512 rather than uint64_t here because a nPowTargetTimespan of more than 3 days in the divisor may cause the following cubic approximation to overflow a uint64_t
306+ arith_uint512 numerator = 1 ;
307+ arith_uint512 denominator = 1 ;
322308 // Alternatively, ensure that the nPowTargetTimespan (divisor) is small enough such that (2*2*2) * (4 + 11 + 35 + 50) * (divisor)^3 < (2^64 - 1) which is the uint64_t maximum value to leave some room and make overflow extremely unlikely
323309 // assert(divisor <= (3 * 24 * 60 * 60));
324310 // Keep in mind that a large exponent due to being extremely far ahead or behind schedule, especially in case of reviving an abandoned chain, will also lead to overflowing the numerator, so a less accurate approximation should be used in this case
@@ -334,12 +320,12 @@ unsigned int AverageTargetASERT(const CBlockIndex* pindexLast, const CBlockHeade
334320 // numerator *= remainder + divisor; // x+1
335321 // denominator *= divisor;
336322
337- const arith_uint256 bnDivisor (divisor);
338- const arith_uint256 bnRemainder (remainder);
323+ const arith_uint512 bnDivisor (divisor);
324+ const arith_uint512 bnRemainder (remainder);
339325 numerator = numerator * ((4 * bnRemainder*bnRemainder*bnRemainder) + (11 * bnRemainder*bnRemainder * bnDivisor) + (35 * bnRemainder * bnDivisor*bnDivisor) + (50 * bnDivisor*bnDivisor*bnDivisor));
340326 denominator = denominator * (50 * bnDivisor*bnDivisor*bnDivisor);
341- // numerator = numerator * ((4ull * remainder*remainder*remainder) + (11ull * remainder*remainder * divisor) + (35ull * remainder * divisor*divisor) + (50ull * divisor*divisor*divisor));
342- // denominator = denominator * (50ull * divisor*divisor*divisor);
327+ // numerator = numerator * ((4lu * remainder*remainder*remainder) + (11lu * remainder*remainder * divisor) + (35lu * remainder * divisor*divisor) + (50lu * divisor*divisor*divisor));
328+ // denominator = denominator * (50lu * divisor*divisor*divisor);
343329 }
344330 } else {
345331 for (int i = 0 ; i > exponent; i--)
@@ -349,12 +335,12 @@ unsigned int AverageTargetASERT(const CBlockIndex* pindexLast, const CBlockHeade
349335 // numerator *= divisor;
350336 // denominator *= remainder + divisor; // x+1
351337
352- const arith_uint256 bnDivisor (divisor);
353- const arith_uint256 bnRemainder (remainder);
338+ const arith_uint512 bnDivisor (divisor);
339+ const arith_uint512 bnRemainder (remainder);
354340 numerator = numerator * (50 * bnDivisor*bnDivisor*bnDivisor);
355341 denominator = denominator * ((4 * bnRemainder*bnRemainder*bnRemainder) + (11 * bnRemainder*bnRemainder * bnDivisor) + (35 * bnRemainder * bnDivisor*bnDivisor) + (50 * bnDivisor*bnDivisor*bnDivisor));
356- // numerator = numerator * (50ull * divisor*divisor*divisor);
357- // denominator = denominator * ((4ull * remainder*remainder*remainder) + (11ull * remainder*remainder * divisor) + (35ull * remainder * divisor*divisor) + (50ull * divisor*divisor*divisor));
342+ // numerator = numerator * (50lu * divisor*divisor*divisor);
343+ // denominator = denominator * ((4lu * remainder*remainder*remainder) + (11lu * remainder*remainder * divisor) + (35lu * remainder * divisor*divisor) + (50lu * divisor*divisor*divisor));
358344 }
359345 }
360346
0 commit comments