Example #1
0
unsigned int GetNextWorkRequiredV4(const CBlockIndex* pindexLast, const Consensus::Params& params, int algo)
{
	// find first block in averaging interval
	// Go back by what we want to be nAveragingInterval blocks per algo
	const CBlockIndex* pindexFirst = pindexLast;
	for (int i = 0; pindexFirst && i < NUM_ALGOS*params.nAveragingInterval; i++)
	{
		pindexFirst = pindexFirst->pprev;
	}

	const CBlockIndex* pindexPrevAlgo = GetLastBlockIndexForAlgo(pindexLast, params, algo);
	if (pindexPrevAlgo == nullptr || pindexFirst == nullptr)
	{
		return InitialDifficulty(params, algo);
	}

	// Limit adjustment step
	// Use medians to prevent time-warp attacks
	int64_t nActualTimespan = pindexLast-> GetMedianTimePast() - pindexFirst->GetMedianTimePast();
	nActualTimespan = params.nAveragingTargetTimespanV4 + (nActualTimespan - params.nAveragingTargetTimespanV4)/4;

	if (nActualTimespan < params.nMinActualTimespanV4)
		nActualTimespan = params.nMinActualTimespanV4;
	if (nActualTimespan > params.nMaxActualTimespanV4)
		nActualTimespan = params.nMaxActualTimespanV4;

	//Global retarget
	arith_uint256 bnNew;
	bnNew.SetCompact(pindexPrevAlgo->nBits);

	bnNew *= nActualTimespan;
	bnNew /= params.nAveragingTargetTimespanV4;

	//Per-algo retarget
	int nAdjustments = pindexPrevAlgo->nHeight + NUM_ALGOS - 1 - pindexLast->nHeight;
	if (nAdjustments > 0)
	{
		for (int i = 0; i < nAdjustments; i++)
		{
			bnNew *= 100;
			bnNew /= (100 + params.nLocalTargetAdjustment);
		}
	}
	else if (nAdjustments < 0)//make it easier
	{
		for (int i = 0; i < -nAdjustments; i++)
		{
			bnNew *= (100 + params.nLocalTargetAdjustment);
			bnNew /= 100;
		}
	}

	if (bnNew > UintToArith256(params.powLimit))
	{
		bnNew = UintToArith256(params.powLimit);
	}

	return bnNew.GetCompact();
}
Example #2
0
unsigned int GetNextWorkRequiredV2(const CBlockIndex* pindexLast, const Consensus::Params& params, int algo)
{
	LogPrintf("Height (Before): %s\n", pindexLast->nHeight);

	// find previous block with same algo
	const CBlockIndex* pindexPrev = GetLastBlockIndexForAlgo(pindexLast, params, algo);

	// find first block in averaging interval
	// Go back by what we want to be nAveragingInterval blocks
	const CBlockIndex* pindexFirst = pindexPrev;
	for (int i = 0; pindexFirst && i < params.nAveragingInterval - 1; i++)
	{
		pindexFirst = pindexFirst->pprev;
		pindexFirst = GetLastBlockIndexForAlgo(pindexFirst, params, algo);
	}

	if (pindexFirst == nullptr)
	{
		LogPrintf("Use default POW Limit\n");
		return InitialDifficulty(params, algo);
	}

	// Limit adjustment step
	int64_t nActualTimespan = pindexPrev->GetBlockTime() - pindexFirst->GetBlockTime();
	if (nActualTimespan < params.nMinActualTimespan)
		nActualTimespan = params.nMinActualTimespan;
	if (nActualTimespan > params.nMaxActualTimespan)
		nActualTimespan = params.nMaxActualTimespan;

	// Retarget

	arith_uint256 bnNew;
	bnNew.SetCompact(pindexPrev->nBits);
	bnNew *= nActualTimespan;
	bnNew /= params.nAveragingTargetTimespan;

	if (bnNew > UintToArith256(params.powLimit))
	{
		bnNew = UintToArith256(params.powLimit);
	}

	return bnNew.GetCompact();	
}
Example #3
0
unsigned int KimotoGravityWell(const CBlockIndex* pindexLast, int algo) {
	
	unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit(algo).GetCompact();
	if (fDebug){
    LogPrintf("Proof Of Work Limit For Algo %i, is % i\n", algo, nProofOfWorkLimit);
    }
    // Genesis block
    if (pindexLast == NULL){
		LogPrintf("Genesis Block Difficulty");
        return nProofOfWorkLimit;
	}
	const CBlockIndex* pindexPrevAlgo = GetLastBlockIndexForAlgo(pindexLast, algo);
    if (pindexPrevAlgo == NULL){
		LogPrintf("pindexPrevAlgo == NULL for Algo %i, is % i\n", algo, nProofOfWorkLimit);
        return nProofOfWorkLimit;
	}
    /* Franko Multi Algo Gravity Well */
    const CBlockIndex   *BlockLastSolved                 = pindexPrevAlgo;
    const CBlockIndex   *BlockReading                    = pindexPrevAlgo;

	unsigned int		 AlgoCounter					 = 0;
    uint64_t             PastBlocksMass                  = 0;
    int64_t              PastRateActualSeconds           = 0;
    int64_t              PastRateTargetSeconds           = 0;
    double               PastRateAdjustmentRatio         = double(1);
    uint256              PastDifficultyAverage;
    uint256              PastDifficultyAveragePrev;
    uint256              BlockReadingDifficulty;
    double               EventHorizonDeviation;
    double               EventHorizonDeviationFast;
    double               EventHorizonDeviationSlow;

    static const int64_t TargetBlockSpacing              = 60; // == 1 minute
    unsigned int         TimeDaySeconds                  = 60 * 60 * 24;
    int64_t              PastSecondsMin                  = TimeDaySeconds * 0.25; // == 6300 Seconds
    int64_t              PastSecondsMax                  = TimeDaySeconds * 7; // == 604800 Seconds
    uint64_t             PastBlocksMin                   = PastSecondsMin / TargetBlockSpacing; // == 360 blocks
    uint64_t             PastBlocksMax                   = PastSecondsMax / TargetBlockSpacing; // == 10080 blocks

	//loop through and count the blocks found by the algo
	for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
        if (PastBlocksMax > 0 && i > PastBlocksMax) { break; }
		// Makes sure we are only calculating blocks from the specified algo
		if (BlockReading->GetAlgo() != algo){ BlockReading = BlockReading->pprev; continue; }
		AlgoCounter++;
		BlockReading = BlockReading->pprev;
	}

    if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 ||
        (uint64_t)BlockLastSolved->nHeight < PastBlocksMin ||
			AlgoCounter < PastBlocksMin) {
        return Params().ProofOfWorkLimit(algo).GetCompact();
    }
    
    int64_t LatestBlockTime = BlockLastSolved->GetBlockTime();


    BlockReading = pindexPrevAlgo;
    for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
        if (PastBlocksMax > 0 && i > AlgoCounter) { break; }
		// Makes sure we are only calculating blocks from the specified algo
		if (BlockReading->GetAlgo() != algo){ BlockReading = BlockReading->pprev; continue; }

        PastBlocksMass++;

        if (i == 1) {
            PastDifficultyAverage.SetCompact(BlockReading->nBits);
        } else {
            BlockReadingDifficulty.SetCompact(BlockReading->nBits);
            if (BlockReadingDifficulty > PastDifficultyAveragePrev) {
                PastDifficultyAverage = PastDifficultyAveragePrev + ((BlockReadingDifficulty - PastDifficultyAveragePrev) / i);
            } else {
                PastDifficultyAverage = PastDifficultyAveragePrev - ((PastDifficultyAveragePrev - BlockReadingDifficulty) / i);
            }
        }
        PastDifficultyAveragePrev = PastDifficultyAverage;

        if (LatestBlockTime < BlockReading->GetBlockTime()) {
                LatestBlockTime = BlockReading->GetBlockTime();
        }
        PastRateActualSeconds = LatestBlockTime - BlockReading->GetBlockTime();
        PastRateTargetSeconds = TargetBlockSpacing * PastBlocksMass;
        PastRateAdjustmentRatio = double(1);
        
        if (PastRateActualSeconds < 1) { PastRateActualSeconds = 1; }
        
        if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
            PastRateAdjustmentRatio = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
        }
        EventHorizonDeviation                   = 1 + (0.7084 * pow((double(PastBlocksMass)/double(144)), -1.228));
        EventHorizonDeviationFast               = EventHorizonDeviation;
        EventHorizonDeviationSlow               = 1 / EventHorizonDeviation;

        if (PastBlocksMass >= PastBlocksMin) {
            if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) ||
                (PastRateAdjustmentRatio >= EventHorizonDeviationFast)) {
                assert(BlockReading);
                break;
            }
        }
        if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
        BlockReading = BlockReading->pprev;
    }

    uint256 bnNew(PastDifficultyAverage);
    if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
        bnNew *= PastRateActualSeconds;
        bnNew /= PastRateTargetSeconds;
    }
    if (bnNew > Params().ProofOfWorkLimit(algo)) { bnNew = Params().ProofOfWorkLimit(algo); }

    // debug print
       if (fDebug){
        LogPrintf("Franko Multi Algo Gravity Well\n");
    
    LogPrintf("PastRateAdjustmentRatio =  %g    PastRateTargetSeconds = %d    PastRateActualSeconds = %d\n",
               PastRateAdjustmentRatio, PastRateTargetSeconds, PastRateActualSeconds);
    LogPrintf("Before: %08x  %s\n", BlockLastSolved->nBits, uint256().SetCompact(BlockLastSolved->nBits).ToString());
    LogPrintf("After:  %08x  %s\n", bnNew.GetCompact(), bnNew.ToString());
    }
    return bnNew.GetCompact();
}
Example #4
0
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, int algo, const Consensus::Params& params)
{
    unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();

    // Genesis block
    if (pindexLast == NULL)
        return nProofOfWorkLimit;

    if (params.fPowAllowMinDifficultyBlocks)
    {
        // Special difficulty rule for testnet:
        // If the new block's timestamp is more than 2* 10 minutes
        // then allow mining of a min-difficulty block.
        // TODO Myriadcoin: enable this at the next hard fork for testnet
        /*
        if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2)
            return nProofOfWorkLimit;
        */
    }

    // find previous block with same algo
    const CBlockIndex* pindexPrev = GetLastBlockIndexForAlgo(pindexLast, algo);

    // Genesis block check again
    if (pindexPrev == NULL)
        return nProofOfWorkLimit;

    const CBlockIndex* pindexFirst = NULL;

    if( (pindexLast->nHeight >= params.nBlockTimeWarpPreventStart1) && (pindexLast->nHeight < params.nBlockTimeWarpPreventStart2) )
    {
        // find first block in averaging interval
        // Go back by what we want to be nAveragingInterval blocks
        pindexFirst = pindexPrev;
        for (int i = 0; pindexFirst && i < params.nAveragingInterval - 1; i++)
        {
            pindexFirst = pindexFirst->pprev;
            pindexFirst = GetLastBlockIndexForAlgo(pindexFirst, algo);
        }
        if (pindexFirst == NULL)
            return nProofOfWorkLimit; // not nAveragingInterval blocks of this algo available

        // check block before first block for time warp
        const CBlockIndex* pindexFirstPrev = pindexFirst->pprev;
        if (pindexFirstPrev == NULL)
            return nProofOfWorkLimit;
        pindexFirstPrev = GetLastBlockIndexForAlgo(pindexFirstPrev, algo);
        if (pindexFirstPrev == NULL)
            return nProofOfWorkLimit;
        // take previous block if block times are out of order
        if (pindexFirstPrev->GetBlockTime() > pindexFirst->GetBlockTime())
        {
            LogPrintf("  First blocks out of order times, swapping:   %d   %d\n", pindexFirstPrev->GetBlockTime(), pindexFirst->GetBlockTime());
            pindexFirst = pindexFirstPrev;
        }
        
    }
    else if ( (pindexLast->nHeight >= params.nBlockTimeWarpPreventStart2) && (pindexLast->nHeight < params.nBlockTimeWarpPreventStart3) )
    {
        // find first block in averaging interval
        // Go back by what we want to be nAveragingInterval blocks
        pindexFirst = pindexPrev;
        for (int i = 0; pindexFirst && i < params.nAveragingInterval - 1; i++)
        {
            pindexFirst = pindexFirst->pprev;
            pindexFirst = GetLastBlockIndexForAlgo(pindexFirst, algo);
        }
        if (pindexFirst == NULL)
            return nProofOfWorkLimit; // not nAveragingInterval blocks of this algo available

        const CBlockIndex* pindexFirstPrev;
        for ( ;; )
        {
            // check blocks before first block for time warp
            pindexFirstPrev = pindexFirst->pprev;
            if (pindexFirstPrev == NULL)
                return nProofOfWorkLimit;
            pindexFirstPrev = GetLastBlockIndexForAlgo(pindexFirstPrev, algo);
            if (pindexFirstPrev == NULL)
                return nProofOfWorkLimit;
            // take previous block if block times are out of order
            if (pindexFirstPrev->GetBlockTime() > pindexFirst->GetBlockTime())
            {
                LogPrintf("  First blocks out of order times, swapping:   %d   %d\n", pindexFirstPrev->GetBlockTime(), pindexFirst->GetBlockTime());
                pindexFirst = pindexFirstPrev;
            }
            else
                break;
        }        
    }
    else
    {
        // find first block in averaging interval
        // Go back by what we want to be nAveragingInterval blocks
        pindexFirst = pindexPrev;
        for (int i = 0; pindexFirst && i < params.nAveragingInterval - 1; i++)
        {
            pindexFirst = pindexFirst->pprev;
            pindexFirst = GetLastBlockIndexForAlgo(pindexFirst, algo);
            if (pindexFirst == NULL)
            {
                if(fDebug)
                {
                    LogPrintf("pindexFirst is null. returning nProofOfWorkLimit\n");
                }
                return nProofOfWorkLimit;
            }
        }
    }

    int64_t nActualTimespan;
    
    if (pindexLast->nHeight >= params.nBlockTimeWarpPreventStart3)
    {
        nActualTimespan = pindexPrev->GetMedianTimePast() - pindexFirst->GetMedianTimePast();
        if(fDebug)
        {
            LogPrintf("  nActualTimespan = %d before bounds   %d   %d\n", nActualTimespan, pindexPrev->GetMedianTimePast(), pindexFirst->GetMedianTimePast());
        }
    }
    else
    {
        nActualTimespan = pindexPrev->GetBlockTime() - pindexFirst->GetBlockTime();
        if(fDebug)
        {
            LogPrintf("  nActualTimespan = %d before bounds   %d   %d\n", nActualTimespan, pindexPrev->GetBlockTime(), pindexFirst->GetBlockTime());
        }
    }
    
    // Time warp mitigation: Don't adjust difficulty if time is negative
    if ( (pindexLast->nHeight >= params.nBlockTimeWarpPreventStart1) && (pindexLast->nHeight < params.nBlockTimeWarpPreventStart2) )
    {
        if (nActualTimespan < 0)
        {
            if(fDebug)
            {
                LogPrintf("  nActualTimespan negative %d\n", nActualTimespan);
                LogPrintf("  Keeping: %08x \n", pindexPrev->nBits);
            }
            return pindexPrev->nBits;
        }
    }

    if (pindexLast->nHeight >= params.Phase2Timespan_Start)
    {
        return CalculateNextWorkRequiredV2(pindexPrev, pindexFirst, params, algo, nActualTimespan);
    }
    else
    {
        return CalculateNextWorkRequiredV1(pindexPrev, pindexFirst, params, algo, nActualTimespan, pindexLast->nHeight);
    }
}